home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / board / IGNUChess151.lha / GNUChess-1.51 / gnuchess.c < prev    next >
C/C++ Source or Header  |  1994-02-10  |  69KB  |  2,491 lines

  1. /************************************************************************/
  2. /*    C source for CHESS                                                    */
  3. /*                                                                        */
  4. /*    Revision: 4-25-88                                                    */
  5. /*                                                                        */
  6. /*    Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.        */
  7. /*    Copyright (c) 1988   John Stanback                                    */
  8. /*                                                                        */
  9. /*    This file is part of CHESS.                                            */
  10. /*                                                                        */
  11. /* CHESS is distributed in the hope that it will be useful, but WITHOUT    */
  12. /* ANY  WARRANTY.   No  author or distributor accepts responsibility to    */
  13. /* anyone for the consequences of using it or for whether it serves any    */
  14. /* particular  purpose  or  works at all, unless he says so in writing.    */
  15. /* Refer to the CHESS General Public License for full details.            */
  16. /*                                                                        */
  17. /* Everyone  is  granted  permission  to  copy, modify and redistribute    */
  18. /* CHESS,  but only under the conditions described in the CHESS General    */
  19. /* Public  License.   A  copy  of this license is supposed to have been    */
  20. /* given  to  you  along  with  CHESS  so  you can know your rights and    */
  21. /* responsibilities.   It  should  be  in  a file named COPYING.  Among    */
  22. /* other things, the copyright notice and this notice must be preserved    */
  23. /* on all copies.                                                        */
  24. /************************************************************************/
  25. /* This  file has been modified to be compilable with SAS/C 6 for Amiga    */
  26. /* Computers. To optimize compile speed and to make it better to under-    */
  27. /* stand I removed most other machine/compiler specific code.            */
  28. /*                                                                        */
  29. /* Also a blank char here or there improves readability by great means.    */
  30. /*                                                                        */
  31. /* Some if-constructs replaced by "? :" terms                            */
  32. /*                                                                        */
  33. /* Declared this-file-use-only functions as static to make possible        */
  34. /* optimizer inlining                                                    */
  35. /*                                                                        */
  36. /* Michael Böhnisch, 1993                                                */
  37. /* billy@uni-paderborn.de                                                */
  38. /************************************************************************/
  39.  
  40. #include <stdio.h>
  41. #include <ctype.h>
  42.  
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <time.h>
  46.  
  47. #include <clib/alib_protos.h>
  48. #include <proto/icon.h>
  49.  
  50.  
  51. #define ttblsz 16384
  52.  
  53. #include "Proto.h"
  54. #include "Interface.h"
  55.  
  56. /* -------------------------------------------------------------------- */
  57. /* Prototypes for static functions                                        */
  58. /* -------------------------------------------------------------------- */
  59.  
  60. static void        EnPassant(short, short, short, short);
  61. static void        OpeningBook(void);
  62. static short    search(short, short, short, short, short, unsigned short *, short *);
  63. static short    evaluate(short, short, short, short, short);
  64. static int        ProbeTTable(short, short, short *, short *, short *);
  65. static void        PutInTTable(short, short, short, short, short, unsigned short);
  66. static void        ZeroTTable(void);
  67. static void        GenMoves(short, short, short, short);
  68. static void        LinkMove(short, short, short, short);
  69. static void        CaptureList(short, short, short);
  70. static void        MakeMove(short, struct leaf *, short *, short *, short *, short *);
  71. static void        UnmakeMove(short, struct leaf *, short *, short *, short *, short *);
  72. static void        UpdateHashbd(short, short, short, short);
  73. static void        UpdatePieceList(short, short, short );
  74. static void        pick(short, short);
  75. static void        repetition(short *);
  76. static void        ataks(short, short *);
  77. static void        ScoreLoneKing(short, short *);
  78. static short    ScoreKPK(short, short, short, short, short, short);
  79. static short    ScoreKBNK(short, short, short);
  80. static void        KingScan(short, short *);
  81. static void        BRscan(short, short *, short *);
  82. static int        trapped(short, short);
  83. static void        UpdateWeights(void);
  84. static void        BlendBoard(short *, short *, short *);
  85. static void        CopyBoard(short *, short *);
  86.  
  87. #define neutral        2
  88. #define white        0
  89. #define black        1 
  90. #define no_piece    0
  91. #define pawn        1
  92. #define knight        2
  93. #define bishop        3
  94. #define rook        4
  95. #define queen        5
  96. #define king        6
  97. #define valueP        100
  98. #define valueN        350
  99. #define valueB        355
  100. #define valueR        550
  101. #define valueQ        1100
  102. #define valueK        1200
  103. #define ctlP        0x4000
  104. #define ctlN        0x2800
  105. #define ctlB        0x1800
  106. #define ctlR        0x0400
  107. #define ctlQ        0x0200
  108. #define ctlK        0x0100
  109. #define ctlBQ        0x1200
  110. #define ctlRQ        0x0600
  111. #define ctlNN        0x2000
  112. #define pxx            " PNBRQK"
  113. #define qxx            " pnbrqk"
  114. #define rxx            "12345678"
  115. #define cxx            "abcdefgh"
  116. #define check        0x0001
  117. #define capture        0x0002
  118. #define draw        0x0004
  119. #define promote        0x0008
  120. #define cstlmask    0x0010
  121. #define epmask        0x0020
  122. #define exact        0x0040
  123. #define pwnthrt        0x0080
  124. #define truescore    0x0001
  125. #define lowerbound    0x0002
  126. #define upperbound    0x0004
  127. #define maxdepth    30
  128. #define true        1
  129. #define false        0
  130. #define absv(x)        ((x) < 0 ? -(x) : (x))
  131. #define taxicab(a,b) (abs(column[a]-column[b]) + abs(row[a]-row[b]))
  132.  
  133. struct leaf {
  134.     short             f, t, score, reply;
  135.     unsigned short    flags;
  136. };
  137.  
  138. struct GameRec {
  139.     unsigned short    gmove;
  140.     short            score, depth, time, piece, color;
  141.     long            nodes;
  142. };
  143.  
  144. struct TimeControlRec {
  145.     short    moves[2];
  146.     long    clock[2];
  147. };
  148.  
  149. struct BookEntry {
  150.     struct BookEntry    *next;
  151.     unsigned short        *mv;
  152. };
  153.  
  154. struct hashval {
  155.     unsigned long    bd;
  156.     unsigned short    key;
  157. };
  158.  
  159. struct hashentry {
  160.     unsigned long    hashbd;
  161.     unsigned short    mv, flags;
  162.     short            score, depth;
  163. };
  164.  
  165. char    mvstr1[5], mvstr2[5];
  166.  
  167. struct leaf        __far    Tree[2000];
  168. struct GameRec    __far    GameList[240];
  169. struct leaf                *root;
  170.  
  171. short    TrPnt[maxdepth],  board[64],  color[64], row[64], column[64],
  172.         locn[8][8],    Pindex[64],    svalue[64],   PieceList[2][16],
  173.         PieceCnt[2],     atak[2][64],    PawnCnt[2][8],    castld[2],
  174.         kingmoved[2],  mtl[2],  pmtl[2],  emtl[2],  hung[2],  c1, c2,
  175.         *atk1,  *atk2,  *PC1,  *PC2, EnemyKing, mate, post, opponent,
  176.         computer, Sdepth, Awindow, Bwindow, dither;
  177.  
  178. long    ResponseTime, ExtraTime, Level, et, et0, time0, cputimer, ft;
  179.         NodeCnt, evrate, ETnodes, EvalNodes, HashCnt;
  180.  
  181. short    quit,  reverse,  bothsides,  hashflag,  InChk, player, force,
  182.         beep,  wking,  bking,  FROMsquare, TOsquare, timeout, Zscore,
  183.         zwndw,   xwndw,   slk,  INCscore,  HasPawn[2],  HasKnight[2],
  184.         HasBishop[2],   HasRook[2],  HasQueen[2],  ChkFlag[maxdepth],
  185.         CptrFlag[maxdepth],  PawnThreat[maxdepth],  Pscore[maxdepth],
  186.         Tscore[maxdepth],    Threat[maxdepth],    GameCnt,    Game50,
  187.         epsquare, lpost, rcptr, contempt, MaxSearchDepth;
  188.  
  189. struct BookEntry        *Book;
  190. struct TimeControlRec    TimeControl;
  191.  
  192. short    TCflag, TCmoves, TCminutes, OperatorTime,
  193.         otherside[3] = {1, 0, 2},
  194.         rank7[3] = {6, 1, 0};
  195.  
  196. short map[64]= {
  197.     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  198.     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  199.     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  200.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  201.     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  202.     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
  203.     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  204.     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77
  205. };
  206.  
  207. short unmap[120]= {
  208.      0,  1,  2,  3,  4,  5,  6,  7, -1, -1, -1, -1, -1, -1, -1, -1,
  209.      8,  9, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1,
  210.     16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1,
  211.     24, 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
  212.     32, 33, 34, 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, -1,
  213.     40, 41, 42, 43, 44, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1,
  214.     48, 49, 50, 51, 52, 53, 54, 55, -1, -1, -1,- 1, -1, -1, -1, -1,
  215.     56, 57, 58, 59, 60, 61, 62, 63
  216. };
  217.  
  218. short Dcode[120]= {
  219.        0,    1,    1,    1,    1,    1,    1,    1,    0,    0,    0,    0,    0,    0, 0x0E, 0x0F,
  220.     0x10, 0x11, 0x12,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 0x0F, 0x1F,
  221.     0x10, 0x21, 0x11,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 0x0F,    0,    0,
  222.     0x10,    0,    0, 0x11,    0,    0,    0,    0,    0,    0,    0,    0, 0x0F,    0,    0,    0,
  223.     0x10,    0,    0,    0, 0x11,    0,    0,    0,    0,    0,    0, 0x0F,    0,    0,    0,    0,
  224.     0x10,    0,    0,    0,    0, 0x11,    0,    0,    0,    0, 0x0F,    0,    0,    0,    0,    0,
  225.     0x10,    0,    0,    0,    0,    0, 0x11,    0,    0, 0x0F,    0,    0,    0,    0,    0,    0,
  226.     0x10,    0,    0,    0,    0,    0,    0, 0x11
  227. };
  228.  
  229. short Stboard[64]= {
  230.     rook,    knight,    bishop,    queen,    king,    bishop,    knight,    rook,
  231.     pawn,    pawn,    pawn,    pawn,    pawn,    pawn,    pawn,    pawn,
  232.     0,        0,        0,        0,        0,        0,        0,        0,
  233.     0,        0,        0,        0,        0,        0,        0,        0,
  234.     0,        0,        0,        0,        0,        0,        0,        0,
  235.     0,        0,        0,        0,        0,        0,        0,        0,
  236.     pawn,    pawn,    pawn,    pawn,    pawn,    pawn,    pawn,    pawn,
  237.     rook,    knight,    bishop,    queen,    king,    bishop,    knight,    rook
  238. };
  239.  
  240. short Stcolor[64]= {
  241.     white,    white,    white,    white,    white,    white,    white,    white,
  242.     white,    white,    white,    white,    white,    white,    white,    white,
  243.     2,        2,        2,        2,        2,        2,        2,        2,
  244.     2,        2,        2,        2,        2,        2,        2,        2,
  245.     2,        2,        2,        2,        2,        2,        2,        2,
  246.     2,        2,        2,        2,        2,        2,        2,        2,
  247.     black,    black,    black,    black,    black,    black,    black,    black,
  248.     black,    black,    black,    black,    black,    black,    black,    black
  249. };
  250.  
  251. short    sweep[7]    = { false, false, false, true, true, true, false},
  252.         Dpwn[3]        = { 4, 6, 0 },
  253.         Dstart[7]    = { 6, 4, 8, 4, 0, 0, 0 },
  254.         Dstop[7]    = { 7, 5, 15, 7, 3, 7, 7 },
  255.         Dir[16]        = {    1,  0x10,   -1, -0x10, 0x0F, 0x11, -0x0F, -0x11,
  256.                         0x0E, -0x0E, 0x12, -0x12, 0x1F, -0x1F, 0x21, -0x21 },
  257.         Pdir[34]    = {    0, 0x38,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02, 0x35, 0x38,
  258.                         0x35, 0x02,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02,    0, 0x02 },
  259.         pbit[7]        = { 0, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20};
  260.  
  261. unsigned short    killr0[maxdepth], killr1 [maxdepth], killr2[maxdepth],
  262.                 killr3[maxdepth], PrVar[maxdepth],
  263.                 PV, hint, Swag0, Swag1, Swag2, Swag3, Swag4,
  264.                 hashkey;
  265.  
  266. unsigned long    hashbd;
  267.  
  268. struct hashval        hashcode[2][7][64];
  269. struct hashentry    *ttable, *ptbl;
  270. unsigned char        history[8192];
  271.  
  272. short    Mwpawn[64], Mbpawn[64], Mknight[2][64], Mbishop[2][64],
  273.         Mking[2][64], Kfield[2][64],
  274.         value[7]        = { 0, valueP, valueN, valueB, valueR, valueQ, valueK },
  275.         control[7]        = { 0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK },
  276.         PassedPawn0[8]    = { 0, 60, 80, 120, 200, 360, 600, 800 },
  277.         PassedPawn1[8]    = { 0, 30, 40, 60, 100, 180, 300, 800 },
  278.         PassedPawn2[8]    = { 0, 15, 25, 35, 50, 90, 140, 800 },
  279.         PassedPawn3[8]    = { 0, 5, 10, 15, 20, 30, 140, 800 },
  280.         ISOLANI[8]        = { -12, -16, -20, -24, -24, -20, -16, -12 },
  281.         BACKWARD[8]        = { -6, -10, -15, -21, -28, -28, -28, -28 },
  282.         BMBLTY[14]        = { -2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16 },
  283.         RMBLTY[14]        = { 0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14 },
  284.         Kthreat[16]        = { 0, -8, -20, -36, -52, -68, -80, -80,
  285.                             -80, -80, -80, -80, -80, -80, -80, -80 },
  286.         KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK, KBNKsq,
  287.         PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED, PBLOK,
  288.         RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY,
  289.         ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL,
  290.         stage, stage2, Zwmtl, Zbmtl, Developed[2], PawnStorm,
  291.         PawnBonus, BishopBonus, RookBonus,
  292.         KingOpening[64]    = {
  293.               0,   0,  -4, -10, -10,  -4,   0,   0,
  294.              -4,  -4,  -8, -12, -12,  -8,  -4,  -4,
  295.             -12, -16, -20, -20, -20, -20, -16, -12,
  296.             -16, -20, -24, -24, -24, -24, -20, -16,
  297.             -16, -20, -24, -24, -24, -24, -20, -16,
  298.             -12, -16, -20, -20, -20, -20, -16, -12,
  299.              -4,  -4,  -8, -12, -12,  -8,  -4,  -4,
  300.               0,   0,  -4, -10, -10,  -4,   0,   0
  301.         },
  302.         KingEnding[64] = {
  303.              0,  6, 12, 18, 18, 12,  6,  0,
  304.              6, 12, 18, 24, 24, 18, 12,  6,
  305.             12, 18, 24, 30, 30, 24, 18, 12,
  306.             18, 24, 30, 36, 36, 30, 24, 18,
  307.             18, 24, 30, 36, 36, 30, 24, 18,
  308.             12, 18, 24, 30, 30, 24, 18, 12,
  309.              6, 12, 18, 24, 24, 18, 12,  6,
  310.              0,  6, 12, 18, 18, 12,  6,  0
  311.         },
  312.         DyingKing[64] = {
  313.              0,  8, 16, 24, 24, 16,  8,  0,
  314.              8, 32, 40, 48, 48, 40, 32,  8,
  315.             16, 40, 56, 64, 64, 56, 40, 16,
  316.             24, 48, 64, 72, 72, 64, 48, 24,
  317.             24, 48, 64, 72, 72, 64, 48, 24,
  318.             16, 40, 56, 64, 64, 56, 40, 16,
  319.              8, 32, 40, 48, 48, 40, 32,  8,
  320.              0,  8, 16, 24, 24, 16,  8,  0
  321.         },
  322.         KBNK[64] = {
  323.             99,    90,    80,    70,    60,    50,    40,    40,
  324.             90, 80, 60, 50, 40, 30, 20, 40,
  325.             80, 60, 40, 30, 20, 10, 30, 50,
  326.             70, 50, 30, 10,  0, 20, 40, 60,
  327.             60, 40, 20,  0, 10, 30, 50, 70,
  328.             50, 30, 10, 20, 30, 40, 60, 80,
  329.             40, 20, 30, 40, 50, 60, 80, 90,
  330.             40, 40, 50, 60, 70, 80, 90, 99
  331.         },
  332.     pknight[64]= {
  333.              0,  4,  8, 10, 10,  8,  4,  0,
  334.              4,  8, 16, 20, 20, 16,  8,  4,
  335.              8, 16, 24, 28, 28, 24, 16,  8,
  336.             10, 20, 28, 32, 32, 28, 20, 10,
  337.             10, 20, 28, 32, 32, 28, 20, 10,
  338.              8, 16, 24, 28, 28, 24, 16,  8,
  339.              4,  8, 16, 20, 20, 16,  8,  4,
  340.              0,  4,  8, 10, 10,  8,  4,  0
  341.         },
  342.     pbishop[64] = {
  343.             14, 14, 14, 14, 14, 14, 14, 14,
  344.             14, 22, 18, 18, 18, 18, 22, 14,
  345.             14, 18, 22, 22, 22, 22, 18 ,14,
  346.             14, 18, 22, 22, 22, 22, 18 ,14,
  347.             14, 18, 22, 22, 22, 22, 18, 14,
  348.             14, 18, 22, 22, 22, 22, 18, 14,
  349.             14, 22, 18, 18, 18, 18, 22, 14,
  350.             14, 14, 14, 14, 14, 14, 14, 14
  351.         },
  352.     PawnAdvance[64] = {
  353.              0,  0,  0,  0,  0,  0,  0,  0,
  354.              4,  4,  4,  0,  0,  4,  4,  4,
  355.              6,  8,  2, 10, 10,  2,  8,  6,
  356.              6,  8, 12, 16, 16, 12,  8,  6,
  357.              8, 12, 16, 24, 24, 16, 12,  8,
  358.             12, 16, 24, 32, 32, 24, 16, 12,
  359.             12, 16, 24, 32, 32, 24, 16, 12,
  360.              0,  0,  0,  0,  0,  0,  0,  0
  361.         };
  362.  
  363. void main(int argc, char **argv)
  364. {
  365.     char **ttypes;
  366.  
  367.     ttypes        = ArgArrayInit( argc, argv );
  368.     DisplayID    = ModeID( ArgString( ttypes, "DISPLAYMODE", "NTSC:HIGHRES LACE" ) );
  369.     ArgArrayDone();
  370.  
  371.     ttable            = (struct hashentry *) malloc(ttblsz * sizeof(struct hashentry));
  372.     Level            = 0;
  373.     OperatorTime     = 0;
  374.     TCmoves            = 40;
  375.     TCminutes        = 30;
  376.     TCflag            = true;
  377.  
  378.     Initialize();
  379.     NewGame();
  380.     while ( !(quit) ) {
  381.         if ( bothsides && !mate )
  382.             SelectMove(opponent, 1);
  383.         else
  384.             InputCommand();
  385.         if ( !(quit || mate || force) )
  386.             SelectMove(computer, 1);
  387.     }
  388.     ExitChess(0);
  389. }
  390.  
  391. /* ...............    INTERFACE ROUTINES    ........................... */
  392.  
  393. /************************************************************************/
  394. /* Compare  the string 's' to the list of legal moves available for the    */
  395. /* opponent.  If a match is found, make the move on the board.            */
  396. /************************************************************************/
  397.  
  398. int VerifyMove(char *s, short iop, unsigned short *mv)
  399. {
  400.     static short        pnt, tempb, tempc, tempsf, tempst, cnt;
  401.     static struct leaf    xnode;
  402.     struct leaf            *node;
  403.  
  404.     *mv = 0;
  405.     if ( iop == 2 ) {
  406.         UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  407.         return false;
  408.     }
  409.     cnt = 0;
  410.     MoveList(opponent, 2);
  411.     pnt = TrPnt[2];
  412.     while ( pnt < TrPnt[3] ) {
  413.         node = &Tree[pnt++];
  414.         algbr(node->f, node->t, node->flags & cstlmask);
  415.         if ( strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0 ) {
  416.             cnt++;
  417.             xnode = *node;
  418.         }
  419.     }
  420.     if ( cnt == 1 ) {
  421.         MakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  422.         if ( SqAtakd(PieceList[opponent][0], computer) ) {
  423.             UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  424.             ShowMessage("Illegal Move!!");
  425.             return(false);
  426.         }
  427.         else {
  428.             if ( iop == 1 )
  429.                 return true;
  430.             if ( xnode.flags & epmask )
  431.                 UpdateDisplay(0, 0, 1, 0);
  432.             else
  433.                 UpdateDisplay(xnode.f, xnode.t, 0, xnode.flags & cstlmask);
  434.             if ( xnode.flags & cstlmask )
  435.                 Game50 = GameCnt;
  436.               else
  437.                 if ( board[xnode.t] == pawn || (xnode.flags & capture) ) 
  438.                     Game50 = GameCnt;
  439.             GameList[GameCnt].depth =
  440.             GameList[GameCnt].score =
  441.             GameList[GameCnt].nodes = 0;
  442.             ElapsedTime(1);
  443.             GameList[GameCnt].time = (short) et;
  444.             TimeControl.clock[opponent] -= et;
  445.             --TimeControl.moves[opponent];
  446.             *mv = (xnode.f << 8) + xnode.t;
  447.             algbr(xnode.f, xnode.t, false);
  448.             return true;
  449.         } 
  450.     }
  451.     if ( cnt > 1 )
  452.         ShowMessage("Ambiguous Move!");
  453.     return false ;
  454. }
  455.  
  456. /************************************************************************/
  457. /* Reset the board and other variables to start a new game.                */
  458. /************************************************************************/
  459.  
  460. void NewGame(void)
  461. {
  462.     short    l, r, c, p;
  463.  
  464.     mate                =
  465.     quit                =
  466.     force                =
  467.     PawnStorm            =
  468.     Developed[white]    =
  469.     Developed[black]    =
  470.     castld[white]        =
  471.     castld[black]        =
  472.     PawnThreat[0]        =
  473.     CptrFlag[0]            =
  474.     Threat[0]            = false;
  475.     rcptr                = true;
  476.     lpost                =
  477.     NodeCnt                =
  478.     epsquare            =
  479.     et0                    =
  480.     contempt            =
  481.     dither                 =
  482.     Game50                =
  483.     Zwmtl                =
  484.     Zbmtl                =
  485.     kingmoved[white]    =
  486.     kingmoved[black]    = 0;
  487.     GameCnt                = -1;
  488.     Pscore[0]            =
  489.     Tscore[0]            = 12000;
  490.     for ( r = 0; r < 8; r++ )
  491.         for ( c = 0; c < 8; c++ ) {
  492.             l            = 8 * r + c;
  493.             locn[r][c]    = l;
  494.             row[l]        = r;
  495.             column[l]    = c;
  496.             board[l]    = Stboard[l];
  497.             color[l]    = Stcolor[l];
  498.         }
  499.     for ( c = white; c <= black; c++ )
  500.         for ( p = pawn; p <= king; p++ )
  501.             for ( l = 0; l < 64; l++ ) {
  502.                 hashcode[c][p][l].key    = (unsigned short) rand();
  503.                 hashcode[c][p][l].bd    = ((unsigned long) rand() << 16) + (unsigned long) rand();
  504.             }
  505.     ClrScreen();
  506.     if ( TCflag )
  507.         SetTimeControl();
  508.     else
  509.         if ( Level == 0 )
  510.             SelectLevel();
  511.     UpdateDisplay(0, 0, 1, 0);
  512.     InitializeStats();
  513.     time0 = time(NULL);
  514.     ElapsedTime(1);
  515.     GetOpenings();
  516. }
  517.  
  518.  
  519. void algbr(short f, short t, short iscastle)
  520. {
  521.     mvstr1[0] = cxx[column[f]];
  522.     mvstr1[1] = rxx[row[f]];
  523.     mvstr1[2] = cxx[column[t]];
  524.     mvstr1[3] = rxx[row[t]];
  525.     mvstr2[0] = qxx[board[f]];
  526.     mvstr2[1] = mvstr1[2];
  527.     mvstr2[2] = mvstr1[3];
  528.     mvstr1[4] = '\0';
  529.     mvstr2[3] = '\0';
  530.     if ( iscastle )
  531.         strcpy(mvstr2, (t>f) ? "o-o" : "o-o-o");
  532. }
  533.  
  534.  
  535. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  536.  
  537. /************************************************************************/
  538. /* Select  a  move by calling function search() at progressively deeper    */
  539. /* ply  until  time  is up or a mate or draw is reached.  An alpha-beta    */
  540. /* window  of  -90  to +90 points is set around the score returned from    */
  541. /* the  previous  iteration.   If  Sdepth  !=  0  then  the program has    */
  542. /* correctly  predicted the opponents move and the search will start at    */
  543. /* a depth of Sdepth+1 rather than a depth of 1.                        */
  544. /************************************************************************/
  545.  
  546. int SelectMove(short side, short iop)
  547. {
  548.     static short    i, alpha, beta, score, tempb, tempc, tempsf, tempst, xside, rpt;
  549.  
  550.     timeout    = false;
  551.     xside    = otherside[side];
  552.     if ( iop != 2 )
  553.         player = side;
  554.     if ( TCflag ) {
  555.         if ( TimeControl.moves[side] + 3 - OperatorTime )
  556.             ResponseTime = TimeControl.clock[side] / TimeControl.moves[side] + 3 - OperatorTime;
  557.         else
  558.             ResponseTime = 0;
  559.         ResponseTime += ResponseTime * TimeControl.moves[side] / ( 2 * TCmoves + 1 );
  560.     }
  561.     else
  562.         ResponseTime = Level;
  563.     if ( iop == 2 )
  564.         ResponseTime = 999;
  565.     if ( Sdepth > 0 && root->score > Zscore-zwndw )
  566.         ResponseTime -= ft;
  567.     else
  568.         if ( ResponseTime < 1 )
  569.             ResponseTime = 1;
  570.     ExtraTime = 0;
  571.     ExaminePosition();
  572.     ScorePosition(side, &score);
  573.     ShowSidetomove();
  574.  
  575.     if ( Sdepth == 0 ) {
  576.         ZeroTTable();
  577.         SearchStartStuff(side);
  578.         memset(history, 0, 8192);
  579.         FROMsquare = TOsquare = -1;
  580.         PV = 0;
  581.         if ( iop != 2 )
  582.             hint = 0;
  583.         for ( i = 0; i < maxdepth; i++ )
  584.             PrVar[i]    =
  585.             killr0[i]    =
  586.             killr1[i]    =
  587.             killr2[i]    =
  588.             killr3[i]    = 0;
  589.         alpha        = score-90;
  590.         beta        = score+90;
  591.         rpt            =
  592.         TrPnt[1]    = 0;
  593.         root        = &Tree[0];
  594.         MoveList(side, 1);
  595.         for ( i = TrPnt[1]; i < TrPnt[2]; i++ )
  596.             pick( i, TrPnt[2] - 1 );
  597.         if ( Book != NULL )
  598.             OpeningBook();
  599.         if ( Book != NULL )
  600.             timeout = true;
  601.         NodeCnt        =
  602.         ETnodes        =
  603.         EvalNodes     =
  604.         HashCnt        =
  605.         Zscore        = 0;
  606.         zwndw        = 20;
  607.     }
  608.  
  609.     while ( ! timeout && Sdepth < MaxSearchDepth ) {
  610.         Sdepth++;
  611.         ShowDepth(' ');
  612.         score = search(side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  613.         for ( i = 1; i <= Sdepth; i++ )
  614.             killr0[i] = PrVar[i];
  615.         if ( score < alpha ) {
  616.             ShowDepth('-');
  617.             ExtraTime = 10 * ResponseTime;
  618.             ZeroTTable();
  619.             score = search(side, 1, Sdepth, -9000, beta, PrVar, &rpt);
  620.         }
  621.         if ( score > beta && ! (root->flags & exact) ) {
  622.             ShowDepth('+');
  623.             ExtraTime = 0;
  624.             ZeroTTable();
  625.             score = search(side, 1, Sdepth, alpha, 9000, PrVar, &rpt);
  626.         }
  627.         score = root->score;
  628.         if ( ! timeout )
  629.             for ( i = TrPnt[1]+1; i < TrPnt[2]; i++ )
  630.                 pick(i, TrPnt[2]-1);
  631.         ShowResults(score, PrVar, '.');
  632.         for ( i = 1; i <= Sdepth; i++ )
  633.             killr0[i] = PrVar[i];
  634.         if ( score > Zscore-zwndw && score > Tree[1].score+250 )
  635.             ExtraTime = 0;
  636.         else
  637.             ExtraTime = (score > Zscore-3*zwndw) ? ResponseTime : 3 * ResponseTime;
  638.         if ( (root->flags & exact) || (Tree[1].score < -9000) || (4*et > 2*ResponseTime+ExtraTime) )
  639.             timeout = true;
  640.         if ( ! timeout ) {
  641.             Tscore[0]    = score;
  642.             Zscore        = Zscore ? (Zscore+score)/2 : score;
  643.         }
  644.         zwndw    = 20 + abs(Zscore / 12);
  645.         beta    = score + Bwindow;
  646.         alpha    = (Zscore < score) ? Zscore-Awindow-zwndw : score-Awindow-zwndw;
  647.     }
  648.  
  649.     score = root->score;
  650.     if ( rpt >= 2 || score < -12000 )
  651.         root->flags |= draw;
  652.     if ( iop == 2 )
  653.         return 0;
  654.     if ( Book == NULL )
  655.         hint = PrVar[2];
  656.     ElapsedTime(1);
  657.  
  658.     if ( score > -9999 && rpt <= 2 ) {
  659.         MakeMove(side, root, &tempb, &tempc, &tempsf, &tempst);
  660.         algbr(root->f, root->t, root->flags & cstlmask);
  661.     }
  662.     else
  663.         mvstr1[0] = '\0';
  664.     OutputMove();
  665.     if ( score == -9999 || score == 9998 )
  666.         mate = true;
  667.     if ( mate )
  668.         hint = 0;
  669.     if ( root->flags & cstlmask )
  670.         Game50 = GameCnt;
  671.     else
  672.         if ( board[root->t] == pawn || (root->flags & capture) )
  673.             Game50 = GameCnt;
  674.     GameList[GameCnt].score    = score;
  675.     GameList[GameCnt].nodes    = NodeCnt;
  676.     GameList[GameCnt].time    = (short) et;
  677.     GameList[GameCnt].depth    = Sdepth;
  678.     if ( TCflag ) {
  679.         TimeControl.clock[side] -= et + OperatorTime;
  680.         if ( --TimeControl.moves[side] == 0 )
  681.             SetTimeControl();
  682.     }
  683.     if ( ((root->flags & draw) && bothsides) || (GameCnt > 238) )
  684.         quit = true;
  685.     player = xside;
  686.     Sdepth = 0;
  687.     return(0);
  688. }
  689.  
  690. /************************************************************************/
  691. /* Go thru each of the opening lines of play and check for a match with    */
  692. /* the  current  game  listing.   If  a match occurs, generate a random    */
  693. /* number.   If  this  number  is the largest generated so far then the    */
  694. /* next  move  in this line becomes the current "candidate".  After all    */
  695. /* lines  are  checked,  the  candidate  move  is put at the top of the    */
  696. /* Tree[]  array  and  will  be  played  by the program.  Note that the    */
  697. /* program does not handle book transpositions.                            */
  698. /************************************************************************/
  699.  
  700. static void OpeningBook(void)
  701. {
  702.     short                j, pnt;
  703.     unsigned short        m, *mp;
  704.     unsigned            r, r0;
  705.     struct BookEntry    *p;
  706.  
  707.     srand((unsigned) time0);
  708.     r0    =
  709.     m    = 0;
  710.     p    = Book;
  711.     while ( p != NULL ) {
  712.         mp = p->mv;
  713.         for ( j = 0; j <= GameCnt; j++ )
  714.             if ( GameList[j].gmove != *(mp++) )
  715.                 break;
  716.         if ( j > GameCnt )
  717.             if ( (r = rand()) > r0 ) {
  718.                 r0        = r;
  719.                 m        = *mp;
  720.                 hint    = *(++mp);
  721.             }
  722.             p = p->next;
  723.     }
  724.     
  725.     for ( pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++ )
  726.         if ( (Tree[pnt].f<<8) + Tree[pnt].t == m )
  727.             Tree[pnt].score = 0;
  728.     pick(TrPnt[1], TrPnt[2] - 1);
  729.     if ( Tree[TrPnt[1]].score < 0 )
  730.         Book = NULL;
  731. }
  732.  
  733.  
  734. #define UpdateSearchStatus                                                    \
  735. {                                                                            \
  736.     if ( post ) ShowCurrentMove(pnt, node->f, node->t);                        \
  737.         if ( pnt > TrPnt[1] ) {                                                \
  738.             d = best-Zscore; e = best-node->score;                            \
  739.             if ( best < alpha )                                                \
  740.                 ExtraTime = 10 * ResponseTime;                                \
  741.             else                                                            \
  742.                 if ( d > -zwndw && e > 4*zwndw )                            \
  743.                     ExtraTime = -ResponseTime / 3;                            \
  744.                 else                                                        \
  745.                     if ( d > -zwndw )                                        \
  746.                         ExtraTime = 0;                                        \
  747.                     else                                                    \
  748.                         if ( d > -3 * zwndw )                                \
  749.                             ExtraTime = ResponseTime;                        \
  750.                         else                                                \
  751.                             if ( d > -9 * zwndw )                            \
  752.                                 ExtraTime = 3 * ResponseTime;                \
  753.                             else                                            \
  754.                                 ExtraTime = 5 * ResponseTime;                \
  755.         }                                                                    \
  756. }
  757.  
  758. /************************************************************************/
  759. /* Perform  an alpha-beta search to determine the score for the current    */
  760. /* board position.  If depth <= 0 only capturing moves, pawn promotions    */
  761. /* and  responses  to  check  are generated and searched, otherwise all    */
  762. /* moves  are  processed.   The  search  depth  is  modified  for check    */
  763. /* evasions,  certain re-captures and threats.  Extensions may continue    */
  764. /* for up to 11 ply beyond the nominal search depth.                    */
  765. /************************************************************************/
  766.  
  767. static short search(short side, short ply, short depth, short alpha, short beta,
  768.     unsigned short *bstline, short *rpt)
  769.  
  770. #define prune        (cf && score+node->score < alpha)
  771. #define ReCapture    (rcptr && score > alpha && score < beta &&                \
  772.                     ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  773. #define MateThreat    (ply < Sdepth+4 && ply > 4 &&                            \
  774.                     ChkFlag[ply-2] && ChkFlag[ply-4] &&                        \
  775.                     ChkFlag[ply-2] != ChkFlag[ply-4])
  776. {
  777.     short            j, pnt;
  778.     short            best, tempb, tempc, tempsf, tempst;
  779.     short            xside, pbst, d, e, cf, score, rcnt;
  780.     unsigned short    mv, nxtline[maxdepth];
  781.     struct leaf     *node, tmp;
  782.  
  783.     NodeCnt++;
  784.     xside = otherside[side];
  785.     if ( depth < 0 )
  786.         depth = 0;
  787.  
  788.     if ( ply <= Sdepth+3 )
  789.         repetition(rpt);
  790.     else
  791.         *rpt = 0;
  792.     if ( *rpt >= 2 )
  793.         return 0;
  794.  
  795.     score = evaluate(side, xside, ply, alpha, beta);
  796.     if ( score > 9000 ) {
  797.         bstline[ply] = 0;
  798.         return score;
  799.     }
  800.                 
  801.     if ( depth > 0 ) {
  802.         if ( InChk || PawnThreat[ply-1] || ReCapture )
  803.             ++depth;
  804.     }
  805.     else {
  806.         if ( score >= alpha && (InChk || PawnThreat[ply-1] || Threat[ply-1]) )
  807.             ++depth;
  808.         else
  809.             if ( score <= beta && MateThreat )
  810.                 ++depth;
  811.     }
  812.  
  813.     if ( depth > 0 && hashflag && ply > 1 ) {
  814.         ProbeTTable(side, depth, &alpha, &beta, &score);
  815.         bstline[ply]    = PV;
  816.         bstline[ply+1]    = 0;
  817.         if ( beta == -20000 )
  818.             return score;
  819.         if ( alpha > beta )
  820.             return alpha;
  821.     }
  822.  
  823.     d = (Sdepth == 1) ? 7 : 11;
  824.  
  825.     if ( ply > Sdepth+d || (depth < 1 && score > beta) )
  826.         return score;
  827.  
  828.     if ( ply > 1 )
  829.         if ( depth > 0 )
  830.             MoveList(side, ply);
  831.         else
  832.             CaptureList(side, xside, ply);
  833.  
  834.     if ( TrPnt[ply] == TrPnt[ply+1] )
  835.         return score;
  836.  
  837.     cf = (depth < 1 && ply > Sdepth+1 && !ChkFlag[ply-2] && !slk);
  838.  
  839.     best = (depth > 0) ? -12000 : score;
  840.  
  841.     if ( best > alpha )
  842.         alpha = best;
  843.   
  844.     for ( pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply+1] && best <= beta; pnt++ ) {
  845.         if ( ply > 1 )
  846.             pick(pnt, TrPnt[ply+1] - 1);
  847.         node = &Tree[pnt];
  848.         mv = (node->f << 8) + node->t;
  849.         nxtline[ply+1] = 0;
  850.  
  851.         if ( prune )
  852.             break;
  853.         if ( ply == 1 )
  854.             UpdateSearchStatus;
  855.  
  856.         if ( !(node->flags & exact) ) {
  857.             MakeMove(side, node, &tempb, &tempc, &tempsf, &tempst);
  858.             CptrFlag[ply]    = node->flags & capture;
  859.             PawnThreat[ply]    = node->flags & pwnthrt;
  860.             Tscore[ply]        = node->score;
  861.             PV                = node->reply;
  862.             node->score        = -search(xside, ply+1, depth-1, -beta, -alpha, nxtline, &rcnt);
  863.             if ( abs(node->score) > 9000 )
  864.                 node->flags |= exact;
  865.             else
  866.                 if ( rcnt == 1 )
  867.                     node->score /= 2;
  868.             if ( rcnt >= 2 || GameCnt-Game50 > 99 || (node->score == 9999-ply && !ChkFlag[ply]) ) {
  869.                 node->flags |= draw | exact;
  870.                 node->score  = (side == computer) ? contempt : -contempt;
  871.             }
  872.             node->reply = nxtline[ply+1];
  873.             UnmakeMove(side, node, &tempb, &tempc, &tempsf, &tempst);
  874.         }
  875.         if ( node->score > best && !timeout ) {
  876.             if ( depth > 0 )
  877.                 if ( node->score > alpha && !(node->flags & exact) )
  878.                     node->score    += depth;
  879.                     best         = node->score;
  880.                     pbst         = pnt;
  881.                     if ( best > alpha )
  882.                         alpha = best;
  883.                     for ( j = ply+1; nxtline[j] > 0; j++ )
  884.                         bstline[j] = nxtline[j];
  885.                     bstline[j] = 0;
  886.                     bstline[ply] = mv;
  887.                     if ( ply == 1 ) {
  888.                         if ( best == alpha ) {
  889.                             tmp = Tree[pnt];
  890.                             for ( j = pnt-1; j >= 0; j-- )
  891.                                 Tree[j+1] = Tree[j];
  892.                             Tree[0]    = tmp;
  893.                             pbst    = 0;
  894.                         }
  895.                         if ( Sdepth > 2 )
  896.                             ShowResults(best, bstline, (best < alpha) ? '-' : ((best > beta) ? '+' : '&'));
  897.                     }
  898.         }
  899.         if ( NodeCnt > ETnodes )
  900.             ElapsedTime(0);
  901.         if ( timeout )
  902.             return (short) -Tscore[ply-1];
  903.     }
  904.  
  905.     node    = &Tree[pbst];
  906.     mv        = (node->f<<8) + node->t;
  907.     if ( hashflag && ply <= Sdepth && *rpt == 0 && best == alpha )
  908.         PutInTTable(side, best, depth, alpha, beta, mv);
  909.     if ( depth > 0 ) {
  910.         j = (node->f<<6) + node->t;
  911.         if ( side == black )
  912.             j |= 0x1000;
  913.         if ( history[j] < 150 )
  914.             history[j] += 2 * depth;
  915.         if ( node->t != (GameList[GameCnt].gmove & 0xFF) )
  916.             if ( best <= beta )
  917.                 killr3[ply] = mv;
  918.             else
  919.                 if ( mv != killr1[ply] ) {
  920.                     killr2[ply] = killr1[ply];
  921.                     killr1[ply] = mv;
  922.                 }
  923.         killr0[ply] = (best > 9000) ? mv : 0;
  924.     }
  925.     return best;
  926. }
  927.  
  928. /************************************************************************/
  929. /* Compute an estimate of the score by adding the positional score from    */
  930. /* the  previous  ply  to the material difference.  If this score falls    */
  931. /* inside a window which is 180 points wider than the alpha-beta window    */
  932. /* (or  within  a  50  point  window  during  quiescence  search)  call    */
  933. /* ScorePosition() to determine a score, otherwise return the estimated    */
  934. /* score.   If  one  side  has  only a king and the other either has no    */
  935. /* pawns or no pieces then the function ScoreLoneKing() is called.        */
  936. /************************************************************************/
  937.  
  938. static short evaluate(short side, short xside, short ply, short alpha, short beta)
  939. {
  940.     short s, evflag;
  941.  
  942.     hung[white]    =
  943.     hung[black]    = 0;
  944.     slk = (    (mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
  945.             (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
  946.     s = -Pscore[ply-1] + mtl[side] - mtl[xside] - INCscore;
  947.  
  948.     evflag    = slk ?
  949.                 false    :
  950.                 ((ply == 1 || ply < Sdepth || ((ply == Sdepth+1 || ply == Sdepth+2) &&
  951.                 (s > alpha-xwndw && s < beta+xwndw)) ||
  952.                 (ply > Sdepth+2 && s >= alpha-25 && s <= beta+25)));
  953.   
  954.     if ( evflag ) {
  955.         EvalNodes++;
  956.         ataks(side, atak[side]);
  957.         if ( atak[side][PieceList[xside][0]] > 0 )
  958.             return (short) (10001-ply);
  959.         ataks(xside, atak[xside]);
  960.         InChk = (atak[xside][PieceList[side][0]] > 0);
  961.         ScorePosition(side, &s);
  962.     }
  963.     else {
  964.         if ( SqAtakd(PieceList[xside][0],side) )
  965.             return (short) (10001-ply);
  966.         InChk = SqAtakd(PieceList[side][0], xside);
  967.         if ( slk )
  968.             ScoreLoneKing(side, &s);
  969.     }
  970.  
  971.     Pscore[ply]        = s - mtl[side] + mtl[xside];
  972.     ChkFlag[ply-1]    = InChk ? Pindex[TOsquare] : 0;
  973.     Threat[ply-1]    = (hung[side] > 1 && ply == Sdepth+1);
  974.     return s;
  975. }
  976.  
  977. /************************************************************************/
  978. /* Look for the current board position in the transposition table.        */
  979. /************************************************************************/
  980.  
  981. static int ProbeTTable(short side, short depth, short *alpha, short *beta, short *score)
  982. {
  983.     short hindx;
  984.  
  985.     if ( side == white )
  986.             hashkey |= 1;
  987.     else
  988.             hashkey &= 0xFFFE;
  989.     hindx    = hashkey & (ttblsz-1);
  990.     ptbl    = ttable + hindx;
  991.     if ( ptbl->depth >= depth && ptbl->hashbd == hashbd ) {
  992.         HashCnt++;
  993.         PV = ptbl->mv;
  994.         if ( ptbl->flags & truescore ) {
  995.             *score = ptbl->score;
  996.             *beta = -20000;
  997.             return true;
  998.         }
  999. //        else
  1000. //            if ( ptbl->flags & upperbound ) {
  1001. //                if ( ptbl->score < *beta )
  1002. //                    *beta = ptbl->score+1;
  1003. //            }
  1004.         else
  1005.             if ( (ptbl->flags & lowerbound) && (ptbl->score > *alpha) )
  1006.                     *alpha = ptbl->score-1;
  1007.     }
  1008.     return false;
  1009. }
  1010.  
  1011. /************************************************************************/
  1012. /* Store the current board position in the transposition table.            */
  1013. /************************************************************************/
  1014.  
  1015. static void PutInTTable(short side, short score, short depth, short alpha, short beta, unsigned short mv)
  1016. {
  1017.     if ( side == white )
  1018.         hashkey |= 1;
  1019.     else
  1020.         hashkey &= 0xFFFE;
  1021.     ptbl            = ttable + (hashkey & (ttblsz-1));
  1022.     ptbl->hashbd    = hashbd;
  1023.     ptbl->depth        = depth;
  1024.     ptbl->score        = score; 
  1025.     ptbl->mv        = mv;
  1026.     ptbl->flags     = (score < alpha) ? upperbound : ((score > beta) ? lowerbound : truescore);
  1027. }
  1028.  
  1029.  
  1030. static void ZeroTTable(void)
  1031. {
  1032.     int i;
  1033.  
  1034.     if ( hashflag )
  1035.         for (i = 0; i < ttblsz; i++) {
  1036.             ptbl        = ttable + i;
  1037.             ptbl->depth    = 0;
  1038.         }
  1039. }
  1040.  
  1041. /************************************************************************/
  1042. /* Fill  the  array  Tree[]  with all available moves for side to play.    */
  1043. /* Array TrPnt[ply] contains the index into Tree[] of the first move at    */
  1044. /* a ply.                                                                */
  1045. /************************************************************************/
  1046.  
  1047. void MoveList(short side, short ply)
  1048. {
  1049.     short    i;
  1050.     short    xside, f;
  1051.  
  1052.     xside = otherside[side];
  1053.     Swag0 = PV ? PV : killr0[ply];
  1054.     Swag1 = killr1[ply];
  1055.     Swag2 = killr2[ply];
  1056.     Swag3 = killr3[ply];
  1057.     Swag4 = 0;
  1058.  
  1059.     if ( ply > 2 )
  1060.         Swag4 = killr1[ply-2];
  1061.  
  1062.     TrPnt[ply+1]    = TrPnt[ply];
  1063.     Dstart[pawn]    = Dpwn[side];
  1064.     Dstop[pawn]        = Dstart[pawn] + 1;
  1065.  
  1066.     for ( i = PieceCnt[side]; i >= 0; i-- )
  1067.         GenMoves(ply, PieceList[side][i], side, xside);
  1068.     if ( kingmoved[side] == 0 && !castld[side] ) {
  1069.         f = PieceList[side][0];
  1070.         if ( castle(side, f, f+2, 0) ) {
  1071.             LinkMove(ply, f, f+2, xside);
  1072.             Tree[TrPnt[ply+1]-1].flags |= cstlmask;
  1073.         }
  1074.         if ( castle(side, f, f-2, 0) ) {
  1075.             LinkMove(ply, f, f-2, xside);
  1076.             Tree[TrPnt[ply+1]-1].flags |= cstlmask;
  1077.         }
  1078.     }
  1079. }
  1080.  
  1081. /************************************************************************/
  1082. /* Generate  moves  for  a  piece.   The  from  square is mapped onto a    */
  1083. /* special  board and offsets (taken from array Dir[]) are added to the    */
  1084. /* mapped  location.  The newly generated square is tested to see if it    */
  1085. /* falls  off  the board by ANDing the square with 88 HEX.  Legal moves    */
  1086. /* are linked into the tree.                                            */
  1087. /************************************************************************/
  1088.  
  1089. static void GenMoves(short ply, short sq, short side, short xside)
  1090. {
  1091.     short m, u, d;
  1092.     short i, m0, piece; 
  1093.  
  1094.     piece    = board[sq];
  1095.     m0        = map[sq];
  1096.     if ( sweep[piece] )
  1097.         for ( i = Dstart[piece]; i <= Dstop[piece]; i++ ) {
  1098.             d = Dir[i];
  1099.             m = m0+d;
  1100.             while ( !(m & 0x88) ) {
  1101.                 u = unmap[m];
  1102.                 if ( color[u] == neutral ) {
  1103.                     LinkMove(ply,sq,u,xside);
  1104.                     m += d;
  1105.                 }
  1106.                 else {
  1107.                     if ( color[u] == xside )
  1108.                         LinkMove(ply, sq, u, xside);
  1109.                     break;
  1110.                 }
  1111.             }
  1112.         }
  1113.     else
  1114.         if ( piece == pawn ) {
  1115.             if ( side == white && color[sq+8] == neutral ) {
  1116.                 LinkMove(ply, sq, sq+8, xside);
  1117.                 if ( row[sq] == 1 )
  1118.                     if ( color[sq+16] == neutral )
  1119.                         LinkMove(ply, sq, sq+16, xside);
  1120.             }
  1121.             else
  1122.                 if ( side == black && color[sq-8] == neutral ) {
  1123.                     LinkMove(ply,sq,sq-8,xside);
  1124.                     if ( row[sq] == 6 )
  1125.                         if ( color[sq-16] == neutral )
  1126.                             LinkMove(ply,sq,sq-16,xside);
  1127.                 }
  1128.                 for ( i = Dstart[piece]; i <= Dstop[piece]; i++ )
  1129.                     if ( !((m = m0+Dir[i]) & 0x88) ) {
  1130.                         u = unmap[m];
  1131.                         if ( color[u] == xside || u == epsquare )
  1132.                             LinkMove(ply,sq,u,xside);
  1133.                     }
  1134.         }
  1135.         else {
  1136.             for ( i = Dstart[piece]; i <= Dstop[piece]; i++ )
  1137.                 if ( !((m = m0+Dir[i]) & 0x88) ) {
  1138.                     u = unmap[m];
  1139.                     if ( color[u] != side )
  1140.                         LinkMove(ply, sq, u, xside);
  1141.                 }
  1142.         }
  1143. }
  1144.  
  1145. /************************************************************************/
  1146. /* Add  a  move  to  the  tree.   Assign  a bonus to order the moves as */
  1147. /* follows:                                                                */
  1148. /*    1. Principle variation                                                */
  1149. /*    2. Capture of last moved piece                                        */
  1150. /*    3. Other captures (major pieces first)                                */
  1151. /*    4. Killer moves                                                        */
  1152. /*    5. "history" killers                                                */
  1153. /************************************************************************/
  1154.  
  1155. static void LinkMove(short ply, short f, short t, short xside)
  1156. {
  1157.     short            s, z;
  1158.     unsigned short    mv;
  1159.     struct leaf        *node;
  1160.  
  1161.     node        = &Tree[TrPnt[ply+1]];
  1162.     ++TrPnt[ply+1];
  1163.     node->flags    =
  1164.     node->reply    = 0;
  1165.     node->f        = f;
  1166.     node->t        = t;
  1167.     mv            = (f<<8) + t;
  1168.     s            = 0;
  1169.     if ( mv == Swag0 )
  1170.         s = 2000;
  1171.     else
  1172.         if ( mv == Swag1 )
  1173.             s = 60;
  1174.         else
  1175.             if ( mv == Swag2 )
  1176.                 s = 50;
  1177.             else
  1178.                 if ( mv == Swag3 )
  1179.                     s = 40;
  1180.                 else
  1181.                     if ( mv == Swag4 )
  1182.                         s = 30;
  1183.     if ( color[t] != neutral ) {
  1184.         node->flags |= capture;
  1185.         if ( t == TOsquare )
  1186.             s += 500;
  1187.         s += value[board[t]] - board[f];
  1188.     }
  1189.     if ( board[f] == pawn )
  1190.         switch ( row[t] ) {
  1191.             case 0:
  1192.             case 7:
  1193.                 node->flags    |= promote;
  1194.                 s            += 800;
  1195.                 break;
  1196.             case 1:
  1197.             case 6:
  1198.                 node->flags    |= pwnthrt;
  1199.                 s            += 600;
  1200.                 break;
  1201.             default:
  1202.                 if ( t == epsquare )
  1203.                     node->flags |= epmask;
  1204.                 break;
  1205.         }
  1206.     z = (f<<6) + t;
  1207.     if ( xside == white )
  1208.         z |= 0x1000;
  1209.     s += history[z];
  1210.     node->score = s - 20000;
  1211. }
  1212.  
  1213. /************************************************************************/
  1214. /* Generate captures and Pawn promotions only.                            */
  1215. /************************************************************************/
  1216.  
  1217. static void CaptureList(short side, short xside, short ply)
  1218.  
  1219. #define LinkCapture {                                                        \
  1220.     node->f = sq;                                                            \
  1221.     node->t = u;                                                            \
  1222.     node->reply = 0;                                                        \
  1223.     node->flags = capture;                                                    \
  1224.     node->score = value[board[u]] + svalue[board[u]] - piece;                \
  1225.     if ( piece == pawn && (u < 8 || u > 55) ) {                                \
  1226.         node->flags |= promote;                                                \
  1227.         node->score = valueQ;                                                \
  1228.     }                                                                        \
  1229.     ++node;                                                                    \
  1230.     ++TrPnt[ply+1];                                                            \
  1231. }
  1232.  
  1233. {
  1234.     short        m, u;
  1235.     short        d, sq, i, j, j1, j2, m0, r7, d0, piece, *PL;
  1236.     struct leaf    *node;
  1237.  
  1238.     TrPnt[ply+1]    = TrPnt[ply];
  1239.     node            = &Tree[TrPnt[ply]];
  1240.     Dstart[pawn]    = Dpwn[side];
  1241.     Dstop[pawn]        = Dstart[pawn] + 1;
  1242.     if ( side == white ) {
  1243.         r7 = 6;
  1244.         d0 = 8;
  1245.     }
  1246.     else {
  1247.         r7 = 1;
  1248.         d0 = -8;
  1249.     }
  1250.     PL = PieceList[side];
  1251.     for ( i = 0; i <= PieceCnt[side]; i++ ) {
  1252.         sq        = PL[i];
  1253.         m0        = map[sq];
  1254.         piece    = board[sq];
  1255.         j1        = Dstart[piece];
  1256.         j2        = Dstop[piece];
  1257.         if ( sweep[piece] )
  1258.             for ( j = j1; j <= j2; j++ ) {
  1259.                 d = Dir[j];
  1260.                 m = m0+d;
  1261.                 while ( !(m & 0x88) ) {
  1262.                     u = unmap[m];
  1263.                     if ( color[u] == neutral )
  1264.                         m += d;
  1265.                     else {
  1266.                         if ( color[u] == xside )
  1267.                             LinkCapture;
  1268.                         break;
  1269.                     }
  1270.                 }
  1271.             }
  1272.         else {
  1273.             for ( j = j1; j <= j2; j++ )
  1274.                 if ( !((m = m0+Dir[j]) & 0x88) ) {
  1275.                     u = unmap[m];
  1276.                     if ( color[u] == xside )
  1277.                         LinkCapture;
  1278.                 }
  1279.                 if ( piece == pawn && row[sq] == r7 ) {
  1280.                     u = sq+d0;
  1281.                     if ( color[u] == neutral )
  1282.                         LinkCapture;
  1283.                 }
  1284.         }
  1285.     }
  1286. }
  1287.  
  1288. /************************************************************************/
  1289. /* Make or Unmake a castling move.                                        */
  1290. /************************************************************************/
  1291.   
  1292. int castle(short side, short kf, short kt, short iop)
  1293. {
  1294.     short rf, rt, d, t0, xside;
  1295.  
  1296.     xside = otherside[side];
  1297.     if ( kt > kf ) {
  1298.         rf = kf+3;
  1299.         rt = kt-1;
  1300.         d  = 1;
  1301.     }
  1302.     else {
  1303.         rf = kf-4;
  1304.         rt = kt+1;
  1305.         d  = -1;
  1306.     }
  1307.     if ( iop == 0 ) {
  1308.         if (    board[kf] != king                    ||
  1309.                 board[rf] != rook                    ||
  1310.                 color[rf] != side                    ||
  1311.                 color[kt] != neutral                ||
  1312.                 color[rt] != neutral                ||
  1313.                 (d == -1 && color[kt+d] != neutral)    ||
  1314.                 SqAtakd(kf, xside)                    ||
  1315.                 SqAtakd(kt, xside)                    ||
  1316.                 SqAtakd(kf+d, xside)
  1317.         )
  1318.             return false;
  1319.     }
  1320.     else {
  1321.         castld[side] = (iop == 1) ? true : false;
  1322.         if ( iop == 2 ) {
  1323.             t0 = kt; kt = kf; kf = t0;
  1324.             t0 = rt; rt = rf; rf = t0;
  1325.         }
  1326.         board[kt] = king;        color[kt] = side;        Pindex[kt] = 0;
  1327.         board[kf] = no_piece;    color[kf] = neutral;
  1328.         board[rt] = rook;        color[rt] = side;        Pindex[rt] = Pindex[rf];
  1329.         board[rf] = no_piece;    color[rf] = neutral;
  1330.         PieceList[side][Pindex[kt]] = kt;
  1331.         PieceList[side][Pindex[rt]] = rt;
  1332.         if ( hashflag ) {
  1333.             UpdateHashbd(side, king, kf, kt);
  1334.             UpdateHashbd(side, rook, rf, rt);
  1335.         }
  1336.     }
  1337.     return true;
  1338. }
  1339.  
  1340. /************************************************************************/
  1341. /* Make or unmake an en passant move.                                    */
  1342. /************************************************************************/
  1343.  
  1344. static void EnPassant(short xside, short f, short t, short iop)
  1345. {
  1346.     short l;
  1347.  
  1348.     l = (t > f) ? t-8 : t+8;
  1349.     if ( iop == 1 ) {
  1350.         board[l] = no_piece;
  1351.         color[l] = neutral;
  1352.     }
  1353.     else {
  1354.         board[l] = pawn;
  1355.         color[l] = xside;
  1356.     }
  1357.     InitializeStats();
  1358. }
  1359.  
  1360. /************************************************************************/
  1361. /* Update  Arrays  board[],  color[],  and  Pindex[] to reflect the new    */
  1362. /* board  position  obtained  after making the move pointed to by node.    */
  1363. /* Also update miscellaneous stuff that changes when a move is made.    */
  1364. /************************************************************************/
  1365.  
  1366. static void MakeMove(short side, struct leaf *node, short *tempb, short *tempc, short *tempsf, short *tempst)
  1367. {
  1368.     short f, t;
  1369.     short xside, ct, cf;
  1370.  
  1371.     xside        = otherside[side];
  1372.     f            = node->f;
  1373.     t            = node->t;
  1374.     epsquare    = -1;
  1375.     FROMsquare    = f;
  1376.     TOsquare    = t;
  1377.     INCscore    = 0;
  1378.     GameList[++GameCnt].gmove = (f<<8) + t;
  1379.     if ( node->flags & cstlmask ) {
  1380.         GameList[GameCnt].piece = no_piece;
  1381.         GameList[GameCnt].color = side;
  1382.         castle(side, f, t, 1);
  1383.     }
  1384.     else {
  1385.         *tempc    = color[t];
  1386.         *tempb    = board[t];
  1387.         *tempsf    = svalue[f];
  1388.         *tempst    = svalue[t];
  1389.         GameList[GameCnt].piece = *tempb;
  1390.         GameList[GameCnt].color = *tempc;
  1391.         if ( *tempc != neutral ) {
  1392.             UpdatePieceList(*tempc, t, 1);
  1393.             if ( *tempb == pawn )
  1394.                 --PawnCnt[*tempc][column[t]];
  1395.             if ( board[f] == pawn ) {
  1396.                 --PawnCnt[side][column[f]];
  1397.                 ++PawnCnt[side][column[t]];
  1398.                 cf = column[f];
  1399.                 ct = column[t];
  1400.                 if ( PawnCnt[side][ct] > 1+PawnCnt[side][cf] )
  1401.                     INCscore -= 15;
  1402.                 else
  1403.                     if ( PawnCnt[side][ct] < 1+PawnCnt[side][cf] )
  1404.                         INCscore += 15;
  1405.                     else
  1406.                         if ( ct == 0 || ct == 7 || PawnCnt[side][ct+ct-cf] == 0 )
  1407.                             INCscore -= 15;
  1408.             }
  1409.             mtl[xside] -= value[*tempb];
  1410.             if ( *tempb == pawn )
  1411.                 pmtl[xside] -= valueP;
  1412.             if ( hashflag ) UpdateHashbd(xside, *tempb, -1, t);
  1413.             INCscore += *tempst;
  1414.         }
  1415.         color[t]    = color[f];
  1416.         board[t]    = board[f];
  1417.         svalue[t]    = svalue[f];
  1418.         Pindex[t]    = Pindex[f];
  1419.         PieceList[side][Pindex[t]] = t;
  1420.         color[f]    = neutral;
  1421.         board[f]    = no_piece;
  1422.         if ( board[t] == pawn )
  1423.             if ( t-f == 16 )
  1424.                 epsquare = f+8;
  1425.             else
  1426.                 if ( f-t == 16 )
  1427.                     epsquare = f-8;
  1428.         if ( node->flags & promote ) {
  1429.             board[t]    = queen;
  1430.             --PawnCnt[side][column[t]];
  1431.             mtl[side]    += valueQ - valueP;
  1432.             pmtl[side]    -= valueP;
  1433.             HasQueen[side] = true;
  1434.             if ( hashflag ) {
  1435.                 UpdateHashbd(side, pawn, f, -1);
  1436.                 UpdateHashbd(side, queen, f, -1);
  1437.             }
  1438.             INCscore -= *tempsf;
  1439.         } 
  1440.         if ( board[t] == king )
  1441.             ++kingmoved[side];
  1442.         if ( node->flags & epmask )
  1443.             EnPassant(xside, f, t, 1);
  1444.         else
  1445.             if ( hashflag )
  1446.                 UpdateHashbd(side, board[t], f, t);
  1447.     }
  1448. }
  1449.  
  1450. /************************************************************************/
  1451. /* Take back a move.                                                    */
  1452. /************************************************************************/
  1453.  
  1454. static void UnmakeMove( short side, struct leaf *node, short *tempb, short *tempc, short *tempsf, short *tempst)
  1455. {
  1456.     short f, t;
  1457.     short xside;
  1458.  
  1459.     xside        = otherside[side];
  1460.     f            = node->f;
  1461.     t            = node->t;
  1462.     epsquare    = -1;
  1463.     GameCnt--;
  1464.     if ( node->flags & cstlmask )
  1465.         castle(side, f, t, 2);
  1466.     else {
  1467.         color[f]    = color[t];
  1468.         board[f]    = board[t];
  1469.         svalue[f]    = *tempsf;
  1470.         Pindex[f]    = Pindex[t];
  1471.         PieceList[side][Pindex[f]] = f;
  1472.         color[t]    = *tempc;
  1473.         board[t]    = *tempb;
  1474.         svalue[t]    = *tempst;
  1475.         if ( node->flags & promote ) {
  1476.             board[f] = pawn;
  1477.             ++PawnCnt[side][column[t]];
  1478.             mtl[side]    += valueP - valueQ;
  1479.             pmtl[side]    += valueP;
  1480.             if ( hashflag ) {
  1481.                 UpdateHashbd(side, queen, -1, t);
  1482.                 UpdateHashbd(side, pawn, -1, t);
  1483.             }
  1484.         } 
  1485.         if ( *tempc != neutral ) {
  1486.             UpdatePieceList(*tempc, t, 2);
  1487.             if ( *tempb == pawn )
  1488.                 ++PawnCnt[*tempc][column[t]];
  1489.             if ( board[f] == pawn ) {
  1490.                 --PawnCnt[side][column[t]];
  1491.                 ++PawnCnt[side][column[f]];
  1492.             }
  1493.             mtl[xside] += value[*tempb];
  1494.             if ( *tempb == pawn )
  1495.                 pmtl[xside] += valueP;
  1496.             if ( hashflag )
  1497.                 UpdateHashbd(xside, *tempb, -1, t);
  1498.         }
  1499.         if ( board[f] == king )
  1500.             --kingmoved[side];
  1501.         if ( node->flags & epmask )
  1502.             EnPassant(xside, f, t, 2);
  1503.         else
  1504.             if ( hashflag )
  1505.                 UpdateHashbd(side, board[f], f, t);
  1506.     }
  1507. }
  1508.  
  1509. /************************************************************************/
  1510. /* hashbd contains a 32 bit "signature" of the board position.  hashkey    */
  1511. /* contains  a 16 bit code used to address the hash table.  When a move    */
  1512. /* is  made,  XOR'ing  the  hashcode  of moved piece on the from and to    */
  1513. /* squares with the hashbd and hashkey values keeps things current.        */
  1514. /************************************************************************/
  1515.  
  1516. static void UpdateHashbd(short side, short piece, short f, short t)
  1517. {
  1518.     if ( f >= 0 ) {
  1519.         hashbd    ^= hashcode[side][piece][f].bd;
  1520.         hashkey    ^= hashcode[side][piece][f].key;
  1521.     }
  1522.     if ( t >= 0 ) {
  1523.         hashbd    ^= hashcode[side][piece][t].bd;
  1524.         hashkey    ^= hashcode[side][piece][t].key;
  1525.     }
  1526. }
  1527.  
  1528. /************************************************************************/
  1529. /* Update  the  PieceList and Pindex arrays when a piece is captured or    */
  1530. /* when a capture is unmade.                                            */
  1531. /************************************************************************/
  1532.  
  1533. static void UpdatePieceList(short side, short sq, short iop)
  1534. {
  1535.     short i;
  1536.  
  1537.     if ( iop == 1 ) {
  1538.         PieceCnt[side]--;
  1539.         for ( i = Pindex[sq]; i <= PieceCnt[side]; i++ ) {
  1540.             PieceList[side][i]            = PieceList[side][i+1];
  1541.             Pindex[PieceList[side][i]]    = i;
  1542.         }
  1543.     }
  1544.     else {
  1545.         PieceCnt[side]++;
  1546.         PieceList[side][PieceCnt[side]]    = sq;
  1547.         Pindex[sq]                        = PieceCnt[side];
  1548.     }
  1549. }
  1550.  
  1551. /************************************************************************/
  1552. /* Scan  thru  the  board  seeing what's on each square.  If a piece is    */
  1553. /* found, update the variables PieceCnt, PawnCnt, Pindex and PieceList.    */
  1554. /* Also  determine  the  material for each side and set the hashkey and    */
  1555. /* hashbd  variables  to  represent  the current board position.  Array    */
  1556. /* PieceList[side][indx]  contains  the  location  of all the pieces of    */
  1557. /* either  side.  Array Pindex[sq] contains the indx into PieceList for    */
  1558. /* a given square.                                                        */
  1559. /************************************************************************/
  1560.  
  1561. void InitializeStats(void)
  1562. {
  1563.     short i, sq;
  1564.  
  1565.     epsquare = -1;
  1566.     for ( i = 0; i < 8; i++ )
  1567.         PawnCnt[white][i] =
  1568.         PawnCnt[black][i] = 0;
  1569.     mtl[white]        =
  1570.     mtl[black]        =
  1571.     pmtl[white]        =
  1572.     pmtl[black]        =
  1573.     PieceCnt[white]    =
  1574.     PieceCnt[black]    =
  1575.     hashbd            =
  1576.     hashkey            = 0;
  1577.     for ( sq = 0; sq < 64; sq++ )
  1578.         if ( color[sq] != neutral ) {
  1579.             mtl[color[sq]] += value[board[sq]];
  1580.             if ( board[sq] == pawn ) {
  1581.                 pmtl[color[sq]] += valueP;
  1582.                 ++PawnCnt[color[sq]][column[sq]];
  1583.             }
  1584.             Pindex[sq] = (board[sq] == king) ? 0 : ++PieceCnt[color[sq]];
  1585.             PieceList[color[sq]][Pindex[sq]] = sq;
  1586.             hashbd    ^= hashcode[color[sq]][board[sq]][sq].bd;
  1587.             hashkey    ^= hashcode[color[sq]][board[sq]][sq].key;
  1588.         }
  1589. }
  1590.  
  1591. /************************************************************************/
  1592. /* Find  the best move in the tree between indexes p1 and p2.  Swap the    */
  1593. /* best move into the p1 element.                                        */
  1594. /************************************************************************/
  1595.  
  1596. static void pick(short p1, short p2)
  1597. {
  1598.     short        p, s;
  1599.     short        p0, s0;
  1600.     struct leaf    temp;
  1601.  
  1602.     s0 = Tree[p1].score;
  1603.     p0 = p1;
  1604.     for ( p = p1+1; p <= p2; p++ )
  1605.         if ( (s = Tree[p].score) > s0 ) {
  1606.             s0 = s;
  1607.             p0 = p;
  1608.         }
  1609.     if ( p0 != p1 ) {
  1610.         temp        = Tree[p1];
  1611.         Tree[p1]    = Tree[p0];
  1612.         Tree[p0]    = temp;
  1613.     }
  1614. }
  1615.  
  1616. /************************************************************************/
  1617. /* Check for draw by threefold repetition.                                */
  1618. /************************************************************************/
  1619.  
  1620. static void repetition(short *cnt)
  1621. {
  1622.     short            i, c;
  1623.     short            f, t, b[64];
  1624.     unsigned short    m;
  1625.  
  1626.     *cnt = c = 0;
  1627.     if ( GameCnt > Game50+3 ) {
  1628. //        memset((char *)b,0,64*sizeof(short));
  1629.         for ( i = 0; i < 64; b[i++] = 0 ) ;
  1630.         for ( i = GameCnt; i > Game50; i-- ) {
  1631.             m = GameList[i].gmove;
  1632.             f = m>>8;
  1633.             t = m & 0xFF;
  1634.             if ( ++b[f] == 0 )
  1635.                 c--;
  1636.             else
  1637.                 c++;
  1638.             if ( --b[t] == 0 )
  1639.                 c--;
  1640.             else
  1641.                 c++;
  1642.             if ( c == 0 )
  1643.                 (*cnt)++;
  1644.         }
  1645.     }
  1646. }
  1647.  
  1648. /************************************************************************/
  1649. /* See  if any piece with color 'side' ataks sq.  First check for pawns    */
  1650. /* or  king,  then  try other pieces.  Array Dcode is used to check for    */
  1651. /* knight attacks or R,B,Q co-linearity.                                */
  1652. /************************************************************************/
  1653.  
  1654. int SqAtakd(short sq, short side)
  1655. {
  1656.     short m, d;
  1657.     short i, m0, m1, loc, piece, *PL;
  1658.  
  1659.     m1    = map[sq];
  1660.     m    = (side == white) ? m1-0x0F : m1+0x0F;
  1661.     if ( !(m & 0x88) )
  1662.         if ( board[unmap[m]] == pawn && color[unmap[m]] == side )
  1663.             return true;
  1664.     m = (side == white) ? m1-0x11 : m1+0x11;
  1665.     if ( !(m & 0x88) )
  1666.         if (board[unmap[m]] == pawn && color[unmap[m]] == side)
  1667.             return true;
  1668.     if ( distance(sq,PieceList[side][0]) == 1 )
  1669.         return true;
  1670.  
  1671.     PL = PieceList[side];
  1672.     for ( i = 1; i <= PieceCnt[side]; i++ ) {
  1673.         loc        = PL[i];
  1674.         piece    = board[loc];
  1675.         if ( piece == pawn )
  1676.             continue;
  1677.         m0    = map[loc];
  1678.         d    = Dcode[abs(m1-m0)];
  1679.         if ( d == 0 || (Pdir[d] & pbit[piece]) == 0 )
  1680.             continue;
  1681.         if ( piece == knight )
  1682.             return true;
  1683.         else {
  1684.             if ( m1 < m0 )
  1685.                 d = -d;
  1686.             for ( m = m0+d; m != m1; m += d )
  1687.                 if ( color[unmap[m]] != neutral )
  1688.                     break;
  1689.             if ( m == m1 )
  1690.                 return true;
  1691.         }
  1692.     }
  1693.     return false;
  1694. }
  1695.  
  1696. /************************************************************************/
  1697. /* Fill  array  atak[][]  with info about ataks to a square.  Bits 8-15    */
  1698. /* are  set  if  the  piece  (king..pawn)  ataks  the square.  Bits 0-7    */
  1699. /* contain a count of total ataks to the square.                        */
  1700. /************************************************************************/
  1701.  
  1702. static void ataks(short side, short *a)
  1703. {
  1704.     short u, m;
  1705.     short d, c, j, j1, j2, piece, i, m0, sq, *PL;
  1706.  
  1707. //    memset((char *)a,0,64*sizeof(short));
  1708.     for ( u = 0; u < 64; a[u++] = 0 );
  1709.  
  1710.     Dstart[pawn]    = Dpwn[side];
  1711.     Dstop[pawn]        = Dstart[pawn] + 1;
  1712.     PL                = PieceList[side];
  1713.     for ( i = 0; i <= PieceCnt[side]; i++ ) {
  1714.         sq        = PL[i];
  1715.         m0        = map[sq];
  1716.         piece    = board[sq];
  1717.         c        = control[piece];
  1718.         j1        = Dstart[piece];
  1719.         j2        = Dstop[piece];
  1720.         if ( sweep[piece] )
  1721.             for ( j = j1; j <= j2; j++ ) {
  1722.                 d = Dir[j];
  1723.                 m = m0+d;
  1724.                 while ( !(m & 0x88) ) {
  1725.                     u = unmap[m];
  1726.                     a[u] = ++a[u] | c;
  1727.                     if ( color[u] == neutral )
  1728.                         m += d;
  1729.                     else
  1730.                         break;
  1731.                 }
  1732.             }
  1733.         else
  1734.             for ( j = j1; j <= j2; j++ )
  1735.                 if ( !((m = m0+Dir[j]) & 0x88) ) {
  1736.                     u        = unmap[m];
  1737.                     a[u]    = ++a[u] | c;
  1738.                 }
  1739.     }
  1740. }
  1741.  
  1742.  
  1743. /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
  1744.  
  1745. /************************************************************************/
  1746. /* Perform  normal  static  evaluation  of  board position.  A score is    */
  1747. /* generated  for  each  piece  and these are summed to get a score for    */
  1748. /* each side.                                                            */
  1749. /************************************************************************/
  1750.  
  1751. void ScorePosition(short side, short *score)
  1752. {
  1753.     short sq, s;
  1754.     short i, xside,pscore[3];
  1755.  
  1756.     wking            = PieceList[white][0];
  1757.     bking            = PieceList[black][0];
  1758.     UpdateWeights();
  1759.     xside            = otherside[side];
  1760.     pscore[white]    = pscore[black] = 0;
  1761.  
  1762.     for ( c1 = white; c1 <= black; c1++ ) {
  1763.         c2 = otherside[c1];
  1764.         EnemyKing = (c1 == white) ? bking : wking;
  1765.         atk1 = atak[c1];
  1766.         atk2 = atak[c2];
  1767.         PC1  = PawnCnt[c1];
  1768.         PC2  = PawnCnt[c2];
  1769.         for ( i = 0; i <= PieceCnt[c1]; i++ ) {
  1770.             sq    = PieceList[c1][i];
  1771.             s    = SqValue(sq,side);
  1772.             pscore[c1] += s;
  1773.             svalue[sq] = s;
  1774.         }
  1775.     }
  1776.     if ( hung[side] > 1 )
  1777.         pscore[side] += HUNGX;
  1778.     if ( hung[xside] > 1 )
  1779.         pscore[xside] += HUNGX;
  1780.  
  1781.     *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
  1782.     if ( dither )
  1783.         *score += rand() % dither;
  1784.  
  1785.     if ( *score > 0 && pmtl[side] == 0 )
  1786.         if ( emtl[side] < valueR )
  1787.             *score = 0;
  1788.         else
  1789.             if ( *score < valueR )
  1790.                 *score /= 2;
  1791.     if ( *score < 0 && pmtl[xside] == 0 )
  1792.         if ( emtl[xside] < valueR )
  1793.             *score = 0;
  1794.         else
  1795.             if ( -*score < valueR )
  1796.                 *score /= 2;
  1797.   
  1798.     if ( mtl[xside] == valueK && emtl[side] > valueB )
  1799.         *score += 200;
  1800.     if ( mtl[side] == valueK && emtl[xside] > valueB )
  1801.         *score -= 200;
  1802. }
  1803.  
  1804. /************************************************************************/
  1805. /* Static evaluation when loser has only a king and winner has no pawns    */
  1806. /* or no pieces.                                                        */
  1807. /************************************************************************/
  1808.  
  1809. static void ScoreLoneKing(short side, short *score)
  1810. {
  1811.     short winner, loser, king1, king2, s, i;
  1812.  
  1813.     UpdateWeights();
  1814.     winner    = (mtl[white] > mtl[black]) ? white : black;
  1815.     loser    = otherside[winner];
  1816.     king1    = PieceList[winner][0];
  1817.     king2    = PieceList[loser][0];
  1818.     s        = 0;
  1819.  
  1820.     if ( pmtl[winner] > 0 )
  1821.         for ( i = 1; i <= PieceCnt[winner]; i++ )
  1822.             s += ScoreKPK(side, winner, loser, king1, king2, PieceList[winner][i]);
  1823.     else
  1824.         if ( emtl[winner] == valueB + valueN )
  1825.             s = ScoreKBNK(winner, king1, king2);
  1826.         else
  1827.             if ( emtl[winner] > valueB )
  1828.                 s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2);
  1829.     *score = (side == winner) ? s : -s;
  1830. }
  1831.  
  1832. /************************************************************************/
  1833. /* Score King and Pawns versus King endings.                            */
  1834. /************************************************************************/
  1835.  
  1836. static short ScoreKPK(short side, short winner, short loser, short king1, short king2, short sq)
  1837. {
  1838.     short s, r;
  1839.  
  1840.     s = (PieceCnt[winner] == 1) ? 50 : 120;
  1841.     if ( winner == white ) {
  1842.         r = (side == loser) ? row[sq]-1 : row[sq];
  1843.         if ( row[king2] >= r && distance(sq, king2) < 8-r )
  1844.             s += 10*row[sq];
  1845.         else
  1846.             s = 500 + 50 * row[sq];
  1847.         sq +=  (row[sq] < 6) ? 16 : 8;
  1848.     }
  1849.     else {
  1850.         r = (side == loser) ? row[sq]+1 : row[sq];
  1851.         if ( row[king2] <= r && distance(sq, king2) < r+1 )
  1852.             s += 10 * ( 7 - row[sq] );
  1853.         else
  1854.             s = 500 + 50 * ( 7 - row[sq] );
  1855.         sq -= (row[sq] > 1) ? 16 : 8;
  1856.     }
  1857.     return s += 8 * ( taxicab(king2, sq) - taxicab(king1,sq) );
  1858. }
  1859.  
  1860. /************************************************************************/
  1861. /* Score King+Bishop+Knight versus King endings.  This doesn't work all    */
  1862. /* that well but it's better than nothing.                                */
  1863. /************************************************************************/
  1864.  
  1865. static short ScoreKBNK(short winner, short king1, short king2)
  1866. {
  1867.     return (short) (
  1868.             emtl[winner] - 300
  1869.         +    (KBNKsq ? KBNK[locn[row[king2]][7-column[king2]]] : KBNK[king2])
  1870.         -    taxicab(king1,king2)
  1871.         -    distance(PieceList[winner][1],king2)
  1872.         -    distance(PieceList[winner][2],king2));
  1873. }
  1874.  
  1875. /************************************************************************/
  1876. /* Calculate the positional value for the piece on 'sq'.                */
  1877. /************************************************************************/
  1878.  
  1879. short SqValue(short sq, short side)
  1880. {
  1881.     short j, fyle, rank;
  1882.     short s, piece, a1, a2, in_square, r, mob, e, c;
  1883.  
  1884.     piece    = board[sq];
  1885.     a1        = (atk1[sq] & 0x4FFF);
  1886.     a2        = (atk2[sq] & 0x4FFF);
  1887.     rank    = row[sq];
  1888.     fyle    = column[sq];
  1889.     s        = 0;
  1890.  
  1891.     switch ( piece ) {
  1892.         case pawn:
  1893.             switch ( c1 ) {
  1894.                 case white:
  1895.                     s = Mwpawn[sq];
  1896.                     if ( sq == 11 || sq == 12 )
  1897.                         if ( color[sq+8] != neutral )
  1898.                             s += PEDRNK2B;
  1899.                     if ( (fyle == 0 || PC1[fyle-1] == 0) && (fyle == 7 || PC1[fyle+1] == 0) )
  1900.                         s += ISOLANI[fyle];
  1901.                     else
  1902.                         if ( PC1[fyle] > 1 )
  1903.                             s += PDOUBLED;
  1904.                     if ( a1 < ctlP && atk1[sq+8] < ctlP ) {
  1905.                         s += BACKWARD[a2 & 0xFF];
  1906.                         if ( PC2[fyle] == 0 )
  1907.                             s += PWEAKH;
  1908.                         if ( color[sq+8] != neutral )
  1909.                             s += PBLOK;
  1910.                     }
  1911.                     if ( PC2[fyle] == 0 ) {
  1912.                         r = (side == black) ? rank-1 : rank;
  1913.                         in_square = (row[bking] >= r && distance(sq,bking) < 8-r);
  1914.                         e = (a2 == 0 || side == white) ? 0 : 1;
  1915.                         for ( j = sq+8; j < 64; j += 8 )
  1916.                             if ( atk2[j] >= ctlP ) {
  1917.                                 e = 2;
  1918.                                 break;
  1919.                             }
  1920.                             else
  1921.                                 if ( atk2[j] > 0 || color[j] != neutral )
  1922.                                     e = 1;
  1923.                         if ( e == 2 )
  1924.                             s += (stage * PassedPawn3[rank]) / 10;
  1925.                         else
  1926.                             if ( in_square || e == 1 )
  1927.                                 s += (stage*PassedPawn2[rank]) / 10;
  1928.                             else
  1929.                                 s += (emtl[black] > 0) ? (stage*PassedPawn1[rank]) / 10 : PassedPawn0[rank];
  1930.                     }
  1931.                     break;
  1932.  
  1933.                 case black:
  1934.                     s = Mbpawn[sq];
  1935.                     if ( sq == 51 || sq == 52 )
  1936.                         if ( color[sq-8] != neutral )
  1937.                             s += PEDRNK2B;
  1938.                     if ( (fyle == 0 || PC1[fyle-1] == 0) && (fyle == 7 || PC1[fyle+1] == 0) )
  1939.                         s += ISOLANI[fyle];
  1940.                     else
  1941.                         if ( PC1[fyle] > 1 )
  1942.                             s += PDOUBLED;
  1943.                     if ( a1 < ctlP && atk1[sq-8] < ctlP ) {
  1944.                         s += BACKWARD[a2 & 0xFF];
  1945.                         if ( PC2[fyle] == 0 )
  1946.                             s += PWEAKH;
  1947.                         if ( color[sq-8] != neutral )
  1948.                             s += PBLOK;
  1949.                     }
  1950.                     if ( PC2[fyle] == 0 ) {
  1951.                         r = (side == white) ? rank+1 : rank;
  1952.                         in_square = (row[wking] <= r && distance(sq,wking) < r+1);
  1953.                         e = (a2 == 0 || side == black) ? 0 : 1;
  1954.                         for ( j = sq-8; j >= 0; j -= 8 )
  1955.                             if ( atk2[j] >= ctlP ) {
  1956.                                 e = 2;
  1957.                                 break;
  1958.                             }
  1959.                             else
  1960.                                 if ( atk2[j] > 0 || color[j] != neutral )
  1961.                                     e = 1;
  1962.                         s += (e == 2) ?
  1963.                             (stage * PassedPawn3[7-rank]) / 10 :
  1964.                             ((in_square || e == 1) ?
  1965.                                 (stage * PassedPawn2[7-rank]) / 10 :
  1966.                                 ((emtl[white] > 0) ?
  1967.                                     (stage * PassedPawn1[7-rank]) / 10 :
  1968.                                     PassedPawn0[7-rank]));
  1969.                     }
  1970.                     break;
  1971.             }
  1972.             break;
  1973.  
  1974.         case knight:
  1975.             s = Mknight[c1][sq];
  1976.             break;
  1977.  
  1978.         case bishop:
  1979.             s = Mbishop[c1][sq];
  1980.             BRscan(sq, &s, &mob);
  1981.             s += BMBLTY[mob];
  1982.             break;
  1983.  
  1984.         case rook:
  1985.             s += RookBonus;
  1986.             BRscan(sq, &s, &mob);
  1987.             s += RMBLTY[mob];
  1988.             if ( PC1[fyle] == 0 )
  1989.             s += RHOPN;
  1990.             if ( PC2[fyle] == 0 )
  1991.                 s += RHOPNX;
  1992.             if ( rank == rank7[c1] && pmtl[c2] > 100 )
  1993.                 s += 10;
  1994.             if ( stage > 2 )
  1995.                 s += 14 - taxicab(sq, EnemyKing);
  1996.             break;
  1997.  
  1998.         case queen:
  1999.             if ( stage > 2 )
  2000.                 s += 14 - taxicab(sq, EnemyKing);
  2001.             if ( distance(sq, EnemyKing) < 3 )
  2002.                 s += 12;
  2003.             break;
  2004.  
  2005.         case king:
  2006.             s = Mking[c1][sq];
  2007.             if ( KSFTY > 0 )
  2008.                 if ( Developed[c2] || stage > 0 )
  2009.                     KingScan(sq, &s);
  2010.             if ( castld[c1] )
  2011.                 s += KCASTLD;
  2012.             else
  2013.                 if ( kingmoved[c1] )
  2014.                     s += KMOVD;
  2015.  
  2016.             if ( PC1[fyle] == 0 )
  2017.                 s += KHOPN;
  2018.             if ( PC2[fyle] == 0 )
  2019.                 s += KHOPNX;
  2020.             switch ( fyle ) {
  2021.                 case 2:
  2022.                     if ( PC1[0] == 0 )
  2023.                         s += KHOPN;
  2024.                     if ( PC2[0] == 0 )
  2025.                         s += KHOPNX;
  2026.                 case 1:
  2027.                 case 3:
  2028.                 case 7:
  2029.                     if ( PC1[fyle-1] == 0 )
  2030.                         s += KHOPN;
  2031.                     if ( PC2[fyle-1] == 0 )
  2032.                         s += KHOPNX;
  2033.                     break;
  2034.                 case 5:
  2035.                     if ( PC1[7] == 0 )
  2036.                         s += KHOPN;
  2037.                     if ( PC2[7] == 0 )
  2038.                         s += KHOPNX;
  2039.                 case 4:
  2040.                 case 6:
  2041.                 case 0:
  2042.                     if ( PC1[fyle+1] == 0 )
  2043.                         s += KHOPN;
  2044.                     if ( PC2[fyle+1] == 0 )
  2045.                         s += KHOPNX;
  2046.                     break;
  2047.             }
  2048.             break;
  2049.     }
  2050.   
  2051.     if ( a2 > 0 ) {
  2052.         c = (control[piece] & 0x4FFF);
  2053.         if ( a1 == 0 || a2 > c+1 ) {
  2054.             s += HUNGP;
  2055.             ++hung[c1];
  2056.             if ( piece != king && trapped(sq, piece) )
  2057.                 ++hung[c1];
  2058.         }
  2059.         else
  2060.             if ( piece != pawn || a2 > a1 )
  2061.                 if ( a2 >= c || a1 < ctlP )
  2062.                     s += ATAKD;
  2063.     }
  2064.     return s;
  2065. }
  2066.  
  2067. /************************************************************************/
  2068. /* Assign  penalties  if  king  can be threatened by checks, if squares    */
  2069. /* near the king are controlled by the enemy (especially the queen), or    */
  2070. /* if there are no pawns near the king.                                    */
  2071. /************************************************************************/
  2072.  
  2073. static void KingScan(short sq, short *s)
  2074.  
  2075. #define ScoreThreat                                                            \
  2076.     if ( color[u] != c2 )                                                    \
  2077.         if ( atk1[u] == 0 || (atk2[u] & 0xFF) > 1 )                            \
  2078.             ++cnt;                                                            \
  2079.         else                                                                \
  2080.             *s -= 3
  2081. {
  2082.     short m, u;
  2083.     short d, i, m0, cnt, ok;
  2084.  
  2085.     cnt    = 0;
  2086.     m0    = map[sq];
  2087.     if ( HasBishop[c2] || HasQueen[c2] )
  2088.         for ( i = Dstart[bishop]; i <= Dstop[bishop]; i++ ) {
  2089.             d = Dir[i];
  2090.             m = m0+d;
  2091.             while ( !(m & 0x88) ) {
  2092.                 u = unmap[m];
  2093.                 if ( atk2[u] & ctlBQ )
  2094.                     ScoreThreat;
  2095.                 if ( color[u] != neutral )
  2096.                     break;
  2097.                 m += d;
  2098.             }
  2099.         }
  2100.     if ( HasRook[c2] || HasQueen[c2] )
  2101.         for ( i = Dstart[rook]; i <= Dstop[rook]; i++ ) {
  2102.             d = Dir[i]; m = m0+d;
  2103.             while ( !(m & 0x88) ) {
  2104.                 u = unmap[m];
  2105.                 if ( atk2[u] & ctlRQ )
  2106.                     ScoreThreat;
  2107.                 if ( color[u] != neutral )
  2108.                     break;
  2109.                 m += d;
  2110.             }
  2111.         }
  2112.     if ( HasKnight[c2] )
  2113.         for ( i = Dstart[knight]; i <= Dstop[knight]; i++ )
  2114.             if ( !((m = m0+Dir[i]) & 0x88) ) {
  2115.                 u = unmap[m];
  2116.                 if ( atk2[u] & ctlNN )
  2117.                     ScoreThreat;
  2118.             }
  2119.     *s += (KSFTY * Kthreat[cnt]) / 16;
  2120.  
  2121.     cnt    = 0;
  2122.     ok    = false;
  2123.     m0    = map[sq];
  2124.     for ( i = Dstart[king]; i <= Dstop[king]; i++ )
  2125.         if ( !((m = m0+Dir[i]) & 0x88) ) {
  2126.             u = unmap[m];
  2127.             if ( board[u] == pawn )
  2128.                 ok = true;
  2129.             if ( atk2[u] > atk1[u] ) {
  2130.                 ++cnt;
  2131.                 if ( atk2[u] & ctlQ )
  2132.                     if ( atk2[u] > ctlQ+1 && atk1[u] < ctlQ )
  2133.                         *s -= 4*KSFTY;
  2134.             }
  2135.         }
  2136.     if ( !ok )
  2137.         *s -= KSFTY;
  2138.     if ( cnt > 1 )
  2139.         *s -= KSFTY;
  2140. }
  2141.  
  2142. /************************************************************************/
  2143. /* Find  Bishop  and  Rook mobility, XRAY attacks, and pins.  Increment    */
  2144. /* the hung[] array if a pin is found.                                    */
  2145. /************************************************************************/
  2146.  
  2147. static void BRscan(short sq, short *s, short *mob)
  2148. {
  2149.     short m, u;
  2150.     short d, j, m0, piece, pin, *Kf;
  2151.  
  2152.     Kf        = Kfield[c1];
  2153.     *mob    = 0;
  2154.     m0        = map[sq];
  2155.     piece    = board[sq];
  2156.     for ( j = Dstart[piece]; j <= Dstop[piece]; j++ ) {
  2157.         pin    = -1;
  2158.         d    = Dir[j];
  2159.         m    = m0+d;
  2160.         while ( !(m & 0x88) ) {
  2161.             u    = unmap[m];
  2162.             *s    += Kf[u];
  2163.             if ( color[u] == neutral ) {
  2164.                 (*mob)++;
  2165.                 m += d;
  2166.             }
  2167.             else
  2168.                 if ( pin < 0 ) {
  2169.                     if ( board[u] == pawn || board[u] == king )
  2170.                         break;
  2171.                     pin = u;
  2172.                     m += d;
  2173.                 }
  2174.                 else
  2175.                     if ( color[u] == c2 && (board[u] > piece || atk2[u] == 0) ) {
  2176.                         if ( color[pin] == c2 ) {
  2177.                             *s += PINVAL;
  2178.                             if ( atk2[pin] == 0 || atk1[pin] > control[board[pin]]+1 )
  2179.                                 ++hung[c2];
  2180.                         }
  2181.                         else
  2182.                             *s += XRAY;
  2183.                         break;
  2184.                     }
  2185.                     else
  2186.                         break;
  2187.         }
  2188.     }
  2189. }
  2190.  
  2191. /************************************************************************/
  2192. /* See if the attacked piece has unattacked squares to move to.            */
  2193. /************************************************************************/
  2194.  
  2195. static int trapped(short sq, short piece)
  2196. {
  2197.     short u, m, d;
  2198.     short i, m0;
  2199.  
  2200.     m0 = map[sq];
  2201.     if ( sweep[piece] )
  2202.         for ( i = Dstart[piece]; i <= Dstop[piece]; i++ ) {
  2203.             d = Dir[i];
  2204.             m = m0+d;
  2205.             while ( !(m & 0x88) ) {
  2206.                 u = unmap[m];
  2207.                 if ( color[u] == c1 )
  2208.                     break;
  2209.                 if ( atk2[u] == 0 || board[u] >= piece )
  2210.                     return false;
  2211.                 if ( color[u] == c2 )
  2212.                     break;
  2213.                 m += d;
  2214.             }
  2215.     }
  2216.     else
  2217.         if ( piece == pawn ) {
  2218.             u = (c1 == white) ? sq+8 : sq-8;
  2219.             if ( color[u] == neutral && atk1[u] >= atk2[u] )
  2220.                 return false;
  2221.             if ( !((m = m0+Dir[Dpwn[c1]]) & 0x88) )
  2222.                 if ( color[unmap[m]] == c2 )
  2223.                     return false;
  2224.             if ( !((m = m0+Dir[Dpwn[c1]+1]) & 0x88) )
  2225.                 if ( color[unmap[m]] == c2 )
  2226.                     return false;
  2227.         }
  2228.         else {
  2229.             for ( i = Dstart[piece]; i <= Dstop[piece]; i++ )
  2230.                 if ( !((m = m0+Dir[i]) & 0x88) ) {
  2231.                     u = unmap[m];
  2232.                     if ( color[u] != c1 )
  2233.                         if ( atk2[u] == 0 || board[u] >= piece )
  2234.                             return false;
  2235.                 }
  2236.         }
  2237.     return true;
  2238. }
  2239.  
  2240. /************************************************************************/
  2241. /* This  is  done one time before the search is started.  Set up arrays    */
  2242. /* Mwpawn,  Mbpawn,  Mknight,  Mbishop,  Mking  which  are  used in the    */
  2243. /* SqValue() function to determine the positional value of each piece.    */
  2244. /************************************************************************/
  2245.  
  2246. void ExaminePosition(void)
  2247. {
  2248.     short i, sq;
  2249.     short wpadv, bpadv, wstrong, bstrong, z, side, pp, j, val, Pd, fyle, rank;
  2250.  
  2251.     wking = PieceList[white][0];
  2252.     bking = PieceList[black][0];
  2253.     ataks(white, atak[white]);
  2254.     ataks(black, atak[black]);
  2255.     Zwmtl    =
  2256.     Zbmtl    = 0;
  2257.     UpdateWeights();
  2258.     HasPawn[white]        =
  2259.     HasPawn[black]        =
  2260.     HasKnight[white]    =
  2261.     HasKnight[black]    =
  2262.     HasBishop[white]    =
  2263.     HasBishop[black]    =
  2264.     HasRook[white]        =
  2265.     HasRook[black]        =
  2266.     HasQueen[white]        =
  2267.     HasQueen[black]        = 0;
  2268.     for ( side = white; side <= black; side++ )
  2269.         for ( i = 0; i <= PieceCnt[side]; i++ )
  2270.             switch ( board[PieceList[side][i]] ) {
  2271.                 case pawn:
  2272.                     ++HasPawn[side];
  2273.                     break;
  2274.                 case knight:
  2275.                     ++HasKnight[side];
  2276.                     break;
  2277.                 case bishop:
  2278.                     ++HasBishop[side];
  2279.                     break;
  2280.                 case rook:
  2281.                     ++HasRook[side];
  2282.                     break;
  2283.                 case queen:
  2284.                     ++HasQueen[side];
  2285.                     break;
  2286.             }
  2287.     if ( !Developed[white] )
  2288.         Developed[white] = (board[1] != knight && board[2] != bishop && board[5] != bishop && board[6] != knight);
  2289.     if ( !Developed[black] )
  2290.         Developed[black] = (board[57] != knight && board[58] != bishop && board[61] != bishop && board[62] != knight);
  2291.     if ( !PawnStorm && stage < 5 )
  2292.         PawnStorm = ((column[wking] < 3 && column[bking] > 4) || (column[wking] > 4 && column[bking] < 3));
  2293.  
  2294.     CopyBoard(pknight, Mknight[white]);
  2295.     CopyBoard(pknight, Mknight[black]);
  2296.     CopyBoard(pbishop, Mbishop[white]);
  2297.     CopyBoard(pbishop, Mbishop[black]);
  2298.     BlendBoard(KingOpening, KingEnding, Mking[white]);
  2299.     BlendBoard(KingOpening, KingEnding, Mking[black]);
  2300.  
  2301.     for ( sq = 0; sq < 64; sq++ ) {
  2302.         fyle = column[sq];
  2303.         rank = row[sq];
  2304.         wstrong = bstrong = true;
  2305.         for ( i = sq; i < 64; i += 8 )
  2306.             if ( atak[black][i] >= ctlP )
  2307.                 wstrong = false;
  2308.         for ( i = sq; i >= 0; i -= 8 )
  2309.             if ( atak[white][i] >= ctlP )
  2310.                 bstrong = false;
  2311.         wpadv = bpadv = PADVNCM;
  2312.         if ( (fyle == 0 || PawnCnt[white][fyle-1] == 0) && (fyle == 7 || PawnCnt[white][fyle+1] == 0) )
  2313.             wpadv = PADVNCI;
  2314.         if ( (fyle == 0 || PawnCnt[black][fyle-1] == 0) && (fyle == 7 || PawnCnt[black][fyle+1] == 0) )
  2315.             bpadv = PADVNCI;
  2316.         Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
  2317.         Mbpawn[sq] = (bpadv * PawnAdvance[63-sq]) / 10;
  2318.         Mwpawn[sq] += PawnBonus;
  2319.         Mbpawn[sq] += PawnBonus;
  2320.         if ( castld[white] || kingmoved[white] ) {
  2321.             if ( (fyle < 3 || fyle > 4) && distance(sq,wking) < 3 )
  2322.                 Mwpawn[sq] += PAWNSHIELD;
  2323.         }
  2324.         else
  2325.             if ( rank < 3 && (fyle < 2 || fyle > 5) )
  2326.                 Mwpawn[sq] += PAWNSHIELD / 2;
  2327.         if ( castld[black] || kingmoved[black] ) {
  2328.             if ( (fyle < 3 || fyle > 4) && distance(sq,bking) < 3 )
  2329.                 Mbpawn[sq] += PAWNSHIELD;
  2330.         }
  2331.         else
  2332.             if ( rank > 4 && (fyle < 2 || fyle > 5) )
  2333.                 Mbpawn[sq] += PAWNSHIELD / 2;
  2334.         if ( PawnStorm ) {
  2335.             if ( (column[wking] < 4 && fyle > 4) || (column[wking] > 3 && fyle < 3) )
  2336.                 Mwpawn[sq] += 3 * rank - 21;
  2337.             if ( (column[bking] < 4 && fyle > 4) || (column[bking] > 3 && fyle < 3) )
  2338.                 Mbpawn[sq] -= 3 * rank;
  2339.         }
  2340.   
  2341.         Mknight[white][sq] += 10 - distance(sq, bking) - distance(sq, wking);
  2342.         Mknight[black][sq] += 10 - distance(sq, wking) - distance(sq, bking);
  2343.         Mbishop[white][sq] += BishopBonus;
  2344.         Mbishop[black][sq] += BishopBonus;
  2345.         for ( i = 0; i <= PieceCnt[black]; i++ )
  2346.             if ( distance(sq, PieceList[black][i]) < 3 )
  2347.                 Mknight[white][sq] += KNIGHTPOST;
  2348.         for ( i = 0; i <= PieceCnt[white]; i++ )
  2349.             if ( distance(sq,PieceList[white][i]) < 3 )
  2350.                 Mknight[black][sq] += KNIGHTPOST;
  2351.         if ( wstrong )
  2352.             Mknight[white][sq] += KNIGHTSTRONG;
  2353.         if ( bstrong )
  2354.             Mknight[black][sq] += KNIGHTSTRONG;
  2355.         if ( wstrong )
  2356.             Mbishop[white][sq] += BISHOPSTRONG;
  2357.         if ( bstrong )
  2358.             Mbishop[black][sq] += BISHOPSTRONG;
  2359.  
  2360.         if ( HasBishop[white] == 2 )
  2361.             Mbishop[white][sq] += 8;
  2362.         if ( HasBishop[black] == 2 )
  2363.             Mbishop[black][sq] += 8;
  2364.         if ( HasKnight[white] == 2 )
  2365.             Mknight[white][sq] += 5;
  2366.         if ( HasKnight[black] == 2 )
  2367.             Mknight[black][sq] += 5;
  2368.  
  2369.         if ( board[sq] == bishop )
  2370.             KBNKsq = ( (rank & 1) == (fyle & 1) ) ? 0 : 7;
  2371.   
  2372.         Kfield[white][sq] = Kfield[black][sq] = 0;
  2373.         if ( distance(sq, wking) == 1 )
  2374.             Kfield[black][sq] = KATAK;
  2375.         if ( distance(sq,bking) == 1 )
  2376.             Kfield[white][sq] = KATAK;
  2377.  
  2378.         Pd = 0;
  2379.         for ( i = 0; i < 64; i++ )
  2380.             if ( board[i] == pawn ) {
  2381.                 if ( color[i] == white ) {
  2382.                     pp    = true;
  2383.                     z    = (row[i] == 6) ? i+8 : i+16;
  2384.                     for ( j = i+8; j < 64; j += 8 )
  2385.                         if ( atak[black][j] > ctlP || board[j] == pawn )
  2386.                             pp = false;
  2387.                 }
  2388.                 else {
  2389.                     pp    = true;
  2390.                     z    = (row[i] == 1) ? i-8 : i-16;
  2391.                     for ( j = i-8; j >= 0; j -= 8 )
  2392.                         if ( atak[white][j] > ctlP || board[j] == pawn )
  2393.                             pp = false;
  2394.                 }
  2395.                 Pd += pp ? 5 * taxicab(sq, z) : taxicab(sq, z);
  2396.             }
  2397.         if ( Pd != 0 ) {
  2398.             val = (Pd * stage2) / 10;
  2399.             Mking[white][sq] -= val;
  2400.             Mking[black][sq] -= val;
  2401.         }
  2402.     }
  2403. }
  2404.  
  2405. /************************************************************************/
  2406. /* If  material  balance  has  changed,  determine  the  values for the    */
  2407. /* positional evaluation terms.                                            */
  2408. /************************************************************************/
  2409.  
  2410. static void UpdateWeights(void)
  2411. {
  2412.     short tmtl;
  2413.  
  2414.     if ( mtl[white] != Zwmtl || mtl[black] != Zbmtl ) {
  2415.         Zwmtl        = mtl[white];
  2416.         Zbmtl        = mtl[black];
  2417.         emtl[white]    = Zwmtl - pmtl[white] - valueK;
  2418.         emtl[black]    = Zbmtl - pmtl[black] - valueK;
  2419.         tmtl        = emtl[white] + emtl[black];
  2420.         stage = (tmtl > 6600) ?
  2421.                     0 :
  2422.                     ((tmtl < 1400) ?
  2423.                         10 :
  2424.                         (6600 - tmtl) / 520);
  2425.         stage2 = (tmtl > 3600) ?
  2426.                     0 :
  2427.                     ((tmtl < 1400) ?
  2428.                         10 :
  2429.                         (3600 - tmtl) / 220);
  2430.  
  2431.         PEDRNK2B        = -15;                // centre pawn on 2nd rank & blocked
  2432.         PBLOK            =                    // blocked backward pawn
  2433.         PWEAKH             = -4;                // weak pawn on half open file
  2434.         PDOUBLED        = -14;                // doubled pawn
  2435.         KCASTLD            =
  2436.         PAWNSHIELD        = 10 - stage;        // pawn near friendly king
  2437.         PADVNCM            =                    // advanced pawn multiplier
  2438.         RHOPN            =                    // rook on half open file
  2439.         PINVAL            = 10;                // Pin
  2440.         PADVNCI            = 7;                // muliplier for isolated pawn
  2441.         PawnBonus        = stage;
  2442.         KNIGHTPOST        = (stage + 2) / 3;    // knight near enemy pieces
  2443.         KNIGHTSTRONG    =                    // occupies pawn hole
  2444.         BISHOPSTRONG    = (stage + 6) / 2;    // occupies pawn hole
  2445.         BishopBonus        = 2 * stage;
  2446.  
  2447.         RHOPNX            = 4;
  2448.         RookBonus        = 6 * stage;
  2449.  
  2450.         XRAY            = 8;                // Xray attack on piece
  2451.  
  2452.         KHOPN            = (3*stage-30) / 2;    // king on half open file
  2453.         KHOPNX            = KHOPN / 2;
  2454.         KMOVD            = -40 / (stage+1);    // king moved before castling
  2455.         KATAK            = (10-stage) / 2;    // B,R attacks near enemy king
  2456.  
  2457.         KSFTY            = (stage < 8) ? 16-2*stage : 0;
  2458.  
  2459.         ATAKD            = -6;                // defender > attacker
  2460.         HUNGP            = -8;                // each hung piece
  2461.         HUNGX            = -12;                // extra for >1 hung piece
  2462.     }
  2463. }
  2464.  
  2465.  
  2466. short distance(short a, short b)
  2467. {
  2468.     short d1, d2;
  2469.  
  2470.     d1 = abs(column[a]-column[b]);
  2471.     d2 = abs(row[a]-row[b]);
  2472.     return (short) ((d1 > d2) ? d1 : d2);
  2473. }
  2474.  
  2475. static void BlendBoard(short *a, short *b, short *c)
  2476. {
  2477.     int sq;
  2478.  
  2479.     for ( sq = 0; sq < 64; sq++ )
  2480.         c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10;
  2481. }
  2482.  
  2483.  
  2484. static void CopyBoard(short *a, short *b)
  2485. {
  2486.     int sq;
  2487.  
  2488.     for ( sq = 0; sq < 64; sq++ )
  2489.         b[sq] = a[sq];
  2490. }
  2491.